python subprocess.call输出不是交错的

时间:2013-11-21 05:01:07

标签: python subprocess

我有一个运行其他shell脚本的python(v3.3)脚本。我的python脚本还打印消息,如"关于运行脚本X"和"完成运行脚本X"。

当我运行脚本时,我将shell脚本的所有输出与我的print语句分开。我看到这样的事情:

All of script X's output
All of script Y's output
All of script Z's output
About to run script X
Done running script X
About to run script Y
Done running script Y
About to run script Z
Done running script Z

运行shell脚本的代码如下所示:

print( "running command: " + cmnd )
ret_code = subprocess.call( cmnd, shell=True )
print( "done running command")

我写了一个基本的测试脚本而 *没有*看到这种行为。这段代码符合我的期望:

print("calling")
ret_code = subprocess.call("/bin/ls -la", shell=True )
print("back")

有关为什么输出没有交错的任何想法?

2 个答案:

答案 0 :(得分:4)

感谢。这有效,但有一个限制 - 在命令完成之前,您无法看到任何输出。我找到了另一个使用popen的问题(here)的答案,但也让我实时看到了输出。以下是我最终得到的结论:

import subprocess
import sys

cmd = ['/media/sf_git/test-automation/src/SalesVision/mswm/shell_test.sh', '4', '2']
print('running command: "{0}"'.format(cmd))  # output the command.
# Here, we join the STDERR of the application with the STDOUT of the application.
process = subprocess.Popen(cmd, bufsize=1, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in iter(process.stdout.readline, ''):
    line = line.replace('\n', '')
    print(line)
    sys.stdout.flush()
process.wait()                   #  Wait for the underlying process to complete.
errcode = process.returncode      #  Harvest its returncode, if needed.
print( 'Script ended with return code of: ' + str(errcode) )

这使用Popen并允许我查看被调用脚本的进度。

答案 1 :(得分:2)

它与STDOUT和STDERR缓冲有关。您应该使用subprocess.Popen将子进程中的STDOUTSTDERR重定向到您的应用程序中。然后,根据需要输出它们。例如:

import subprocess

cmd = ['ls', '-la']
print('running command: "{0}"'.format(cmd))  # output the command.
# Here, we join the STDERR of the application with the STDOUT of the application.
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
process.wait()  # Wait for the underlying process to complete.
out, err = process.communicate()  # Capture what it outputted on STDOUT and STDERR
errcode = process.returncode  # Harvest its returncode, if needed.
print(out)
print('done running command')

此外,除非确实需要,否则我不会使用shell = True。它强制子进程启动整个shell环境以运行命令。通常最好直接注入Popen的env参数。