我有一个小型Python程序,它从名为pip
的{{1}}包执行终端命令(commandwrapper
的包装器:https://pypi.python.org/pypi/commandwrapper/0.7)。我也试图捕获控制台和文件的实时输出。
我有代码:
subprocess.popen
当我在 PyCharm 中运行它时,这非常有效。 class Tee(object):
def __init__(self, *files):
self.files = files
def write(self, obj):
for f in self.files:
f.write(obj)
f.flush()
def flush(self) :
for f in self.files:
f.flush()
# Set the stdout/stderr to Tee()
out = open(stdout_log, 'w')
stdout_reset = sys.stdout
sys.stdout = Tee(sys.stdout, out)
process = commandwrapper.WrapCommand(command, shell=True) # Also tried False with same behaivor.
cmd = process.prepareToRun()
# Stream the output to the console and stdoutfiles
while cmd.poll() is None:
msg_out = cmd.stdout.readline()
sys.stdout.write(msg_out)
sys.stdout.flush()
out.close()
的输出将写入文件并实时显示在终端控制台上。
但是,当我在终端中运行相同的代码时,控制台上不会显示任何输出。怎么会这样? command
在文件中被正确捕获,但没有任何内容写入控制台。
任何人都可以看到这个代码在PyCharm中运行良好且没有预期的任何原因,但是没有向终端显示任何标准输出?我在这里不知所措。如果有的话,如果行为被逆转,我可以处理它。
使用OSX Yosemite并运行stdout
。
答案 0 :(得分:1)
您需要更改轮询的逻辑,我使用了Popen,但如果您愿意,可以使用包装器:
out = open(stdout_log, 'w')
stdout_reset = sys.stdout
sys.stdout = Tee(sys.stdout, out)
from subprocess import Popen,PIPE,STDOUT
process = Popen([list_of_cmds],stdout=PIPE,stderr=STDOUT)
# Stream the output to the console and stdoutfiles
for line in iter(process.stdout.readline,""):
sys.stdout.write(line)
out.close()
应用相同的逻辑与commandwrapper
lib:
process = commandwrapper.WrapCommand(command, shell=True) # Also tried False with same behaivor.
cmd = process.prepareToRun()
# Stream the output to the console and stdoutfiles
for line in iter(cmd.stdout.readline,""):
sys.stdout.write(line)
答案 1 :(得分:0)
即使子进程已退出,即cmd.poll() is not None
,管道中仍可能存在缓冲输出。如果在cmd.stdout.read()
循环结束后调用while cmd.poll() is not None
,您可以看到它。
要在没有Tee
,commandwrapper
的情况下重现错误:
#!/usr/bin/env python
import sys
import time
from subprocess import Popen, PIPE
#XXX DO NOT USE THE CODE -- ITS PURPOSE IS TO DEMONSTRATE THE ISSUE
p = Popen([sys.executable, '-c', "import os; os.write(1, b'abc')"],
stdout=PIPE, bufsize=0) # no buffering in the parent
time.sleep(0.3) # allow the child to exit
while p.poll() is None: # poll() should return non-None value
assert 0, "it is never run unless the computer is slow"
line = p.stdout.readline()
print(line)
output = p.stdout.read() #
print("the output left after the child has died: %r" % (output,))
assert len(output) >= 3
请参阅这些帖子,了解如何阅读子流程'实时输出以及如何同时将其重定向到文件和终端: