Python 中子进程的实时输出
Realtime output from subprocess in Python
我运行正在使用 Django 网络服务器,并试图将子进程的输出实时打印到日志中。如果我推荐 readline 行并取消注释 yowzer 行,我会得到所需的日志输出流,但是一旦我尝试按原样 运行 我就没有输出。我究竟做错了什么?我能找到的所有结果似乎都表明这可以按原样工作。
sp = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
while sp.poll() is None:
logging.critical(sp.stdout.readline())
#logging.critical('yowzer')
time.sleep(10)
谢谢!
[4 月 3 日编辑] 事实证明问题不是命令太长 运行ning,而是我使用了分号来将 'su user' 命令与主命令连接起来。删除 su 解决了问题。
在 Python 中调用子进程时,获取(或者更确切地说,不获取)实时输出是一个长期的烦恼。有关 in-depth 的讨论,请参阅 this question,但简短的版本是将关键字 arg bufsize=1
添加到 Popen
调用中可能是您需要的秘诀。
还有,你为什么有time.sleep(10)
?您确实意识到这意味着您必须在记录每行之间等待 10 秒,对吗?尝试重组您正在进行的调用以读取输出。假设您使用的是 Python 3,试试这个:
from subprocess import PIPE, Popen
with Popen(command, shell=True, stdout=PIPE, bufsize=1) as sp:
for line in sp.stdout:
logging.critical(line)
我刚刚测试了上面的代码并且可以确认它有效。 Try it out yourself here。链接的测试版本在日志的每一行之前打印一个时间戳。
如果还是不行
如果您调用的子进程不定期刷新它的输出,您在 Python 脚本中无能为力。你提到了 Django,对吧?您尝试记录的输出是通过标准 Python print()
调用生成的吗?如果是这样,您可以修改它们以更积极地刷新:
print(s, flush=True)
我用过的每个 other language 也有一个等效的刷新命令,因此(假设您有权访问 to/can 修改子进程的源代码)您应该能够完成这项工作。
我运行正在使用 Django 网络服务器,并试图将子进程的输出实时打印到日志中。如果我推荐 readline 行并取消注释 yowzer 行,我会得到所需的日志输出流,但是一旦我尝试按原样 运行 我就没有输出。我究竟做错了什么?我能找到的所有结果似乎都表明这可以按原样工作。
sp = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
while sp.poll() is None:
logging.critical(sp.stdout.readline())
#logging.critical('yowzer')
time.sleep(10)
谢谢!
[4 月 3 日编辑] 事实证明问题不是命令太长 运行ning,而是我使用了分号来将 'su user' 命令与主命令连接起来。删除 su 解决了问题。
在 Python 中调用子进程时,获取(或者更确切地说,不获取)实时输出是一个长期的烦恼。有关 in-depth 的讨论,请参阅 this question,但简短的版本是将关键字 arg bufsize=1
添加到 Popen
调用中可能是您需要的秘诀。
还有,你为什么有time.sleep(10)
?您确实意识到这意味着您必须在记录每行之间等待 10 秒,对吗?尝试重组您正在进行的调用以读取输出。假设您使用的是 Python 3,试试这个:
from subprocess import PIPE, Popen
with Popen(command, shell=True, stdout=PIPE, bufsize=1) as sp:
for line in sp.stdout:
logging.critical(line)
我刚刚测试了上面的代码并且可以确认它有效。 Try it out yourself here。链接的测试版本在日志的每一行之前打印一个时间戳。
如果还是不行
如果您调用的子进程不定期刷新它的输出,您在 Python 脚本中无能为力。你提到了 Django,对吧?您尝试记录的输出是通过标准 Python print()
调用生成的吗?如果是这样,您可以修改它们以更积极地刷新:
print(s, flush=True)
我用过的每个 other language 也有一个等效的刷新命令,因此(假设您有权访问 to/can 修改子进程的源代码)您应该能够完成这项工作。