也许在以太中有人可以帮我解决这个问题.(我在SO上已经看到了很多类似的问题,但没有一个涉及标准输出和标准错误或处理与我相似的情况,因此这个新问题.)
我有一个python函数打开一个子进程,等待它完成,然后输出返回代码,以及标准输出和标准错误管道的内容.当进程正在运行时,我还想在填充它们时显示两个管道的输出.我的第一次尝试导致了这样的事情:
process = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout = str()
stderr = str()
returnCode = None
while True:
# collect return code and pipe info
stdoutPiece = process.stdout.read()
stdout = stdout + stdoutPiece
stderrPiece = process.stderr.read()
stderr = stderr + stderrPiece
returnCode = process.poll()
# check for the end of pipes and return code
if stdoutPiece == '' and stderrPiece == '' and returnCode != None:
return returnCode, stdout, stderr
if stdoutPiece != '': print(stdoutPiece)
if stderrPiece != '': print(stderrPiece)
Run Code Online (Sandbox Code Playgroud)
但是有一些问题.因为read()读取直到a EOF,while循环的第一行将不会返回,直到子进程关闭管道.
我可以替换read()赞成read(int)但打印输出失真,在读取字符的末尾切断.我可以readline()作为替代品,但是当同时出现许多两种情况时,打印输出会因交替的输出线和错误而失真.
也许有一种read-until-end-of-buffer()我不知道的变体?或者也许可以实施?
也许最好按照另一篇文章的答案中的sys.stdout建议实现一个包装器?但是,我只想在这个函数中使用包装器.
来自社区的任何其他想法?
我很感激帮助!:)
编辑:解决方案真的应该是跨平台的,但如果你有想法不是,请分享它们以保持头脑风暴.
对于我的另一个python子进程头部抓取器,请看一下关于计算时序中子进程开销的另一个问题.
Ada*_*eld 10
通过使用使管道无阻塞fcntl.fcntl,并使用select.select等待数据在任一管道中可用.例如:
# Helper function to add the O_NONBLOCK flag to a file descriptor
def make_async(fd):
fcntl.fcntl(fd, fcntl.F_SETFL, fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK)
# Helper function to read some data from a file descriptor, ignoring EAGAIN errors
def read_async(fd):
try:
return fd.read()
except IOError, e:
if e.errno != errno.EAGAIN:
raise e
else:
return ''
process = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
make_async(process.stdout)
make_async(process.stderr)
stdout = str()
stderr = str()
returnCode = None
while True:
# Wait for data to become available
select.select([process.stdout, process.stderr], [], [])
# Try reading some data from each
stdoutPiece = read_async(process.stdout)
stderrPiece = read_async(process.stderr)
if stdoutPiece:
print stdoutPiece,
if stderrPiece:
print stderrPiece,
stdout += stdoutPiece
stderr += stderrPiece
returnCode = process.poll()
if returnCode != None:
return (returnCode, stdout, stderr)
Run Code Online (Sandbox Code Playgroud)
请注意,fcntl仅适用于类似Unix的平台,包括Cygwin.
如果你需要它在没有Cygwin的Windows上工作,它是可行的,但它更加困难.你必须:
SetNamedPipeHandleState具有PIPE_NOWAIT使输出和错误管道无阻塞WaitForMultipleObjects而不是select等待数据变得可用ReadFile读取数据| 归档时间: |
|
| 查看次数: |
3472 次 |
| 最近记录: |