我的一个大型项目的一部分包括一个Python部分,如下所示:
failcount = 0
done = False
while done == False:
try:
result = subprocess.check_output(program)
done = True
except subprocess.CalledProcessError as e:
failcount += 1
logwrite('logfile.txt', 'Failed. Counter = {0}\nError message: {1}\n-'.format(failcount, e.returncode))
if failcount == 20:
print 'It failed 20 times, aborting...'
quit()
这意味着从命令行运行“程序”。 “程序”是一个大型计算化学包,有时会失败,所以我在这里循环运行它。如果失败 20 次,那么我的 python 脚本就会终止。这工作得很好并且达到了预期目的。然而,我的问题是我的化学包每次尝试大约需要三个小时,我想监控它的进展。
如果我从命令行手动运行它,我可以简单地执行“program > logfile”,然后 tail -f 日志文件来观察它的运行情况。然而,你似乎不能在 python 中做类似的事情:
subprocess.check_output(['program', '>', 'logfile'])
有没有办法让 python 在 subprocess.check_output 被填充时打印出它的内容?我认为 subprocess.check_output 仅包含标准输出中的内容。我可以以某种方式在 python 和管道之间克隆它吗?
可能的解决方法:我制作了一个名为 run_program.sh 的 bash 脚本,它只执行上面列出的程序 > 日志文件,然后我使用 python 的子进程来执行 run_program.sh。这样我就可以根据需要进行监控,但现在程序的输出在一个文件中,而不是在 python 中,所以我必须让 python 读取一个大的日志文件,并在需要时捕获错误消息,所以我更愿意如果可以避免这样的事情。
最佳答案
您可以使用 subprocess.Popen
而不是使用 subprocess.check_output
。该对象代表您的子进程,并具有您可以读取的 stdout 和 stderr 属性。如果您的子进程仅使用 stdout,您可能只需在循环中调用 Popen.stdout.readline() 即可。但是,如果子进程写入其他管道,则可能会遇到死锁(有关详细信息,请参阅文档)。在这种情况下,我建议使用 http://stefaanlippens.net/python-asynchronous-subprocess-pipe-reading/ 中描述的 consume
函数。 ,它可以安全地让您逐行打印 stdout 和 stderr,因为它是从子进程输出的。
或者,如果您将 shell=True
传递给check_output
函数。 >
是一个 shell 指令,如果您将其作为独立命令运行,则无法识别该指令。
编辑:上面的内容不会返回任何输出供您的 Python 程序使用。相反,subprocess.check_output('program | tee logfile', shell=True)
。
如果使用 shell=True,请注意您可以完全控制 check_output
的参数。为了安全起见,切勿允许任何用户或网络输入传递到 shell。请参阅this warning为什么。
关于python - 使用 python subprocess.check_output 进行实时管道或解决方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48814481/