在搜索之后,我定义了一个执行命令的函数,如终端:
import shlex
import subprocess
def execute_cmd(cmd):
p = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
for line in iter(p.stdout.readline, b''): # b'' here for python3
sys.stdout.write(line.decode(sys.stdout.encoding))
error = p.stderr.read().decode()
if error:
raise Exception(error)
当我
时,它工作正常(输出是实时的)execute_cmd('ping -c 5 www.google.com')
但是,当我使用execute_cmd
运行python脚本时,输出将打印出来,直到该过程完成。
execute_cmd('python test.py')
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time
print('hello')
time.sleep(2)
print('hello, again')
我该如何解决?谢谢!
很抱歉没有解释为什么'抓住stdout然后再将它写入stdout'。在这里,我真正想做的是将脚本输出捕获到记录器,记录器将它们输出到屏幕(StreamHandler)和日志文件(FileHandler)。我建立并测试了记录器部分,现在是“执行”部分。并忽略stdout=
参数似乎不起作用。
由于步骤2,如果我忽略stdout=
参数,脚本的输出仍将输出到STDOUT,并且不会登录文件。
也许我可以将stdout=
设置为记录器?
答案 0 :(得分:1)
这是底层输出系统的常见问题,特别是在Linux或其他类Unix系统上。 io库非常智能,可以在检测到输出定向到终端时刷新每个\n
的输出。但是,当输出重定向到文件或管道时,可能出于性能原因,不会发生此自动刷新。当只有数据很重要时,这不是一个真正的问题,但是当时间也很重要时,它会导致奇怪的行为。
不幸的是,我不知道从调用者程序(*)修复它的简单方法。唯一的可能性是让被调用者强制刷新每个行/块或使用无缓冲输出:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time
import sys
print('hello')
sys.stdout.flush()
time.sleep(2)
print('hello, again')
(*)防弹方式是使用伪终端。调用者控制主端并将客户端传递给被调用者。库将检测终端并将自动刷新每一行。但它不再是在Unix世界之外的可移植性,并且不是真正的简单方式。