10.1.1.2 捕获输出
对于run()启动的进程,它的标准输入和输出通道会绑定到父进程的输入和输出。这说明调用程序无法捕获命令的输出。可以通过为stdout和stderr参数传入PIPE来捕获输出,以备以后处理。
import subprocess
completed = subprocess.run(
['ls','-1'],
stdout = subprocess.PIPE,
)
print('returncode:',completed.returncode)
print('Have {} bytes in stdout:\n{}'.format(
len(completed.stdout),
completed.stdout.decode('utf-8'))
)
ls -1命令成功运行,所以会捕获并返回它打印到标准输出的文本。
说明:传入check=True并设置stdout为PIPE等价于使用check_output()。
运行结果:
下一个例子在一个子shell中运行一系列命令。在命令返回一个错误码并退出之前,消息会发送到标准输出和标准错误输出。
import subprocess
try:
completed = subprocess.run(
'echo to stdout;echo to stderr 1>&2; exit 1',
check=True,
shell=True,
stdout=subprocess.PIPE,
)
except subprocess.CalledProcessError as err:
print('ERROR:',err)
else:
print('returncode:',completed.returncode)
print('Have {} bytes in stdout: {!r}'.format(
len(completed.stdout),
completed.stdout.decode('utf-8'))
发送到标准错误输出的消息会被打印到控制台,而发生到标准输出的消息会被隐藏。
运行结果:
为了避免通过run()运行的命令将错误消息写至控制台,可以设置stderr参数为常量PIPE。
import subprocess
try:
completed = subprocess.run(
'echo to stdout:echo to stderr 1>&2: exit 1',
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
except subprocess.CalledProcessError as err:
print('ERROR:',err)
else:
print('returncode:',completed.returncode)
print('Have {} bytes in stdout: {!r}'.format(
len(completed.stdout),
completed.stdout.decode('utf-8'))
)
print('Have {} bytes in stderr: {!r}'.format(
len(completed.stderr),
completed.stderr.decode('utf-8'))
)
这个例子没有设置check=True,所以会捕获并打印命令的输出。
运行结果:
使用check_output()时如果要捕获错误消息,则要把stderr设置为STDOUT,错误消息将与命令的其他输出合并在一起。
import subprocess
try:
output = subprocess.check_output(
'echo to stdout;echo to stderr 1>&2',
shell=True,
stderr=subprocess.STDOUT,
)
except subprocess.CalledProcessError as err:
print('ERROR:',err)
else:
print('Have {} bytes in output: {!r}'.format(
len(output),
output.decode('utf-8'))
)
输出的顺序可能有所不同,这取决于如何对标准输出应用缓存以及数据如何打印。
运行结果: