子进程在PyCharm中正确显示sys.stdout但在控制台

时间:2015-12-02 23:31:35

标签: python subprocess pycharm stdout

我有一个小型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

2 个答案:

答案 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,您可以看到它。

要在没有Teecommandwrapper的情况下重现错误:

#!/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

请参阅这些帖子,了解如何阅读子流程'实时输出以及如何同时将其重定向到文件和终端: