繁体   English   中英

Python 子进程调用 output 超时

[英]Python subprocess call with output and timeout

总结:我想从 Python(3.6 版)启动一个外部进程,非阻塞地轮询结果,并在超时后终止。

详细信息:有一个带有 2 个“坏习惯”的外部进程:

  1. 它在未定义的时间后打印出相关结果。
  2. 它打印出结果后不会停止。

示例:也许以下简单应用程序大部分类似于要调用的实际程序( mytest.py ;源代码不可用):

import random
import time

print('begin')
time.sleep(10*random.random())
print('result=5')
while True: pass

这就是我试图称呼它的方式:

import subprocess, time
myprocess = subprocess.Popen(['python', 'mytest.py'], stdout=subprocess.PIPE)
for i in range(15):
    time.sleep(1)
    # check if something is printed, but do not wait to be printed anything
    # check if the result is there
    # if the result is there, then break
myprocess.kill()

我想在评论中实现逻辑。

分析

以下是不合适的:

  • 使用myprocess.communicate() ,因为它等待终止,并且子进程不会终止。
  • 杀死进程然后调用myprocess.communicate() ,因为我们不知道结果何时打印出来
  • 使用process.stdout.readline()因为这是一个 blocikg 语句,所以它会等到打印出一些东西。 但这里最后不打印任何东西。

io.BufferedReader myprocess.stdout 所以实际上的问题是:有没有办法检查io.BufferedReader是否打印了某些内容,如果是,请阅读它,否则不要等待?

我想我得到了您需要的确切 package。 认识一下command_runner ,它是一个子进程包装器并允许:

  • 实时标准输出/标准错误 output
  • 超时与执行无关
  • 进程树包括在超时情况下杀死的子进程
  • stdout / stderr 重定向到队列、文件或回调函数

使用pip install command_runner

用法:

from command_runner import command_runner

def callback(stdout_output):
    # Do whatever you want here with the output
    print(stdout_output)

exit_code, output = command_runner("python mytest.py", timeout=300, stdout=callback, method='poller')

if exit_code == -254:
    print("Oh no, we got a timeout")
    print(output)

# Check for good exit_code and full stdout output here

如果达到超时,您将得到 exit_code -254,但仍然会得到 output 填充您的子进程写入 stdout/stderr 的任何内容。

免责声明:我是command_runner的作者

可以在 github 页面上看到使用队列的其他非阻塞示例。

①如果本文未解决您的问题,请点击查看与本文相关的问题
②如果本文未解决您的问题,请向程序员专用AI小助手提问
暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM