如何使用subprocess.Popen从命令获取输出并为stdout和stderr分别进行回调,但是确保按照流程来自流程的顺序调用这些回调?
如果我不关心将STDOUT和STDERR分开,那么我可以这样做:
fd = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
line = fd.stdout.readline()
while line :
callback( line )
line = fd.stdout.readline()
但是,如果我有stdoutCallback
和stderrCallback
,并希望在适当的输出上调用它们,但是按照与上面代码相同的顺序调用callback
,我该怎么办?这样做呢?
答案 0 :(得分:1)
fd = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE )
output,error = fd.communicate()
使用communicate
答案 1 :(得分:1)
所以我认为我已经完成了自己的几个主题。
对于下面的示例,test.py
就是:
#!/usr/bin/python -u
import sys
import time
sys.stdout.write("stdout 1\n")
time.sleep(1)
sys.stderr.write("stderr 2\n")
time.sleep(1)
sys.stdout.write("stdout 3\n")
time.sleep(1)
sys.stderr.write("stderr 4\n")
time.sleep(1)
获取正确输出的代码是:
#!/usr/bin/env python
import subprocess
from threading import Thread, Lock
cmdOutput = []
cmdOutputLock = Lock()
STDOUT = 1
STDERR = 2
def _outputLoop( fd, identifier ) :
line = fd.readline()
while line :
cmdOutputLock.acquire()
cmdOutput.append( ( line, identifier ) )
cmdOutputLock.release()
line = fd.readline()
p = subprocess.Popen( "test.py",
stdout = subprocess.PIPE,
stderr = subprocess.PIPE )
Thread( target=_outputLoop, args=( p.stdout, STDOUT ) ).start()
Thread( target=_outputLoop, args=( p.stderr, STDERR ) ).start()
while fd.poll() is None or cmdOutput :
output = None
cmdOutputLock.acquire()
if cmdOutput :
output = cmdOutput[0]
del cmdOutput[0]
cmdOutputLock.release()
if output :
if output[1] == STDOUT :
print "STDOUT : {}".format( output[0].rstrip() )
elif output[1] == STDERR :
print "STDERR : {}".format( output[0].rstrip() )
我绝对可以想象一下stderr线与stdout线混合在一起的时间,但是为了我想要的东西,它肯定有效。 (我把它作为日志模块的一部分,它将运行命令并为stdout和stderr使用不同的日志级别。)
答案 2 :(得分:1)
这是不可能的。如果对不同的文件执行write
,则没有定义订单。
如果将write
转到stdout,stderr转到同一个地方(例如stdout=PIPE, stderr=STDOUT
案例中),则可以获得正确的订单。
如果“近似”订单足够;这是一个simple code example with threads,这里是single-threaded version with a select
-loop。