2013-11-21 25 views
1

我有一个运行其他shell脚本的python(v3.3)脚本。我的python脚本还会打印“关于运行脚本X”和“完成运行脚本X”等消息。python subprocess.call输出不是交织的

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

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") 

任何想法为什么输出不交错?

回答

4

谢谢。这有效,但有一个限制 - 直到命令完成后才能看到任何输出。我从另一个问题找到了答案(here),它使用了popen,但也让我能够实时看到输出。以下是我最终得到的结果:

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并允许我查看被调用脚本的进度。

+0

很好找。这是非常pythonic!很高兴为你工作。 – VooDooNOFX

+0

注意:在Python 3.3中,你可以使用'in line in process.stdout:'而不是'iter(...)'。此外,你可以使用'print(line,end ='',flush = True)'而不是'line.replace('\ n','');打印(线); sys.stdout.flush()'或使用'line = line.rstrip('\ n')'。在循环后调用'process.stdout.close()'。 – jfs

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参数通常会更好。

+0

谢谢。这有效,但有一个限制 - 直到命令完成后才能看到任何输出。我从另一个使用popen的问题找到答案,但也让我能够实时看到输出。以下是我最终得到的结果: – SecondGear

+0

呃。忽略我以前的评论。我很蹩脚 - 我无法弄清楚如何在评论中发布代码。 – SecondGear

+0

如果'cmd'生成足够的输出,则代码会死锁。如果使用'subprocess.PIPE',则应该排空管道。在'process.communicate()'之前删除'process.wait()'。 – jfs

相关问题