提问人:QuantumChris 提问时间:7/22/2019 更新时间:7/25/2019 访问量:161
强制第三方程序在通过子进程调用时刷新其输出
Force a 3rd-party program to flush its output when called through subprocess
问:
我正在使用第三方 python 模块,该模块通常通过终端命令调用。当通过终端命令调用时,它有一个详细的选项,可以实时打印到终端。
然后我有另一个python程序,它通过子进程调用第三方程序。不幸的是,当通过子进程调用时,终端输出不再刷新,并且仅在完成时返回(该过程需要数小时,因此我希望实时进度)。
我可以看到第三方模块的源代码,它没有将打印设置为刷新,例如.有没有办法在不编辑第三方源代码的情况下强制刷新我的模块?此外,我可以将此输出发送到日志文件(再次实时)吗?print('example', flush=True)
感谢您的帮助。
答:
问题很可能是,如果在终端中或作为管道的一部分以交互方式运行,则许多程序的工作方式可能会有所不同(即称为 using )。它与 Python 本身关系不大,但与 Unix/Linux 架构关系更大。subprocess
如您所指出的,即使在管道中运行时,也可以强制程序刷新,但它需要通过手动应用调用来更改源代码。stdout
stdout.flush
打印到屏幕上的另一种方法是“欺骗”程序,使其认为它正在与交互式终端一起使用,使用所谓的伪终端。Python 标准库中有一个支持模块,即 .使用 that,您不会显式调用 (or or ...)。相反,您必须使用 pty.spawn 调用:pty
subprocess.run
Popen
def prout(fd):
data = os.read(fd, 1024)
while(data):
print(data.decode(), end="")
data = os.read(fd, 1024)
pty.spawn("./callee.py", prout)
可以看出,这需要一个特殊的处理功能。在上面,我只是将其打印到终端,但当然也可以对文本执行其他操作(例如日志或解析......stdout
欺骗程序的另一种方法是使用称为 .Unbuffer 将你的脚本作为输入,并让程序思考(就像调用一样)从终端调用。如果已安装或允许您将其安装在您的系统上(它是软件包的一部分),这可以说是更简单。然后,您所要做的就是将您的呼叫更改为unbuffer
pty
unbuffer
expect
subprocess
p=subprocess.Popen(["unbuffer", "./callee.py"], stdout=subprocess.PIPE)
然后当然像往常一样处理输出,例如使用一些代码,例如
for line in p.stdout:
print(line.decode(), end="")
print(p.communicate()[0].decode(), end="")
或类似。但是最后一部分我认为您已经介绍了,因为您似乎正在对输出做一些事情。
评论