13.6 执行外部命令并获�它的输出¶

问题¶

你想执行一个外部命令并以Python字符串的形�获�执行结果。

解决方案¶

使用 subprocess.check_output() 函数。例如:

import subprocess
out_bytes = subprocess.check_output(['netstat','-a'])

这段代�执行一个指定的命令并将执行结果以一个字节字符串的形�返回。 如果你需�文本形�返回,加一个解�步骤��。例如:

out_text = out_bytes.decode('utf-8')

如果被执行的命令以�零�返回,就会抛出异常。 下�的例��获到错误并获�返回�:

try:
    out_bytes = subprocess.check_output(['cmd','arg1','arg2'])
except subprocess.CalledProcessError as e:
    out_bytes = e.output       # Output generated before error
    code      = e.returncode   # Return code

默认情况下,check_output() 仅仅返回输入到标准输出的值。 如果你需��时收集标准输出和错误输出,使用 stderr �数:

out_bytes = subprocess.check_output(['cmd','arg1','arg2'],
                                    stderr=subprocess.STDOUT)

如果你需�用一个超时机制�执行命令,使用 timeout �数:

try:
    out_bytes = subprocess.check_output(['cmd','arg1','arg2'], timeout=5)
except subprocess.TimeoutExpired as e:
    ...

通常�讲,命令的执行�需�使用到底层shell环境(比如sh�bash)。 一个字符串列表会被传递给一个低级系统命令,比如 os.execve() 。 如果你想让命令被一个shell执行,传递一个字符串�数,并设置�数 shell=True . 有时候你想�Python去执行一个��的shell命令的时候这个就很有用了,比如管���I/O�定�和其他特性。例如:

out_bytes = subprocess.check_output('grep python | wc > out', shell=True)

需�注�的是在shell中执行命令会存在一定的安全风险,特别是当�数�自于用户输入时。 这时候�以使用 shlex.quote() 函数�将�数正确的用�引用引起�。

讨论¶

使用 check_output() 函数是执行外部命令并获�其返回值的最简�方�。 但是,如果你需�对�进程�更��的交互,比如给它��输入,你得采用�外一�方法。 这时候�直接使用 subprocess.Popen 类。例如:

import subprocess

# Some text to send
text = b'''
hello world
this is a test
goodbye
'''

# Launch a command with pipes
p = subprocess.Popen(['wc'],
          stdout = subprocess.PIPE,
          stdin = subprocess.PIPE)

# Send the data and get the output
stdout, stderr = p.communicate(text)

# To interpret as text, decode
out = stdout.decode('utf-8')
err = stderr.decode('utf-8')

subprocess 模�对于�赖TTY的外部命令��适用。 例如,你�能使用它�自动化一个用户输入密�的任务(比如一个ssh会�)。 这时候,你需�使用到第三方模�了,比如基于著�的 expect 家�的工具(pexpect或类似的)