【问题标题】:Python capture subprocess output after terminationPython在终止后捕获子进程输出
【发布时间】:2017-09-17 04:52:00
【问题描述】:

我正在尝试在引发 TimeoutExpired 异常时获取子进程输出(在 Windows 上)。有什么想法吗?

try:
    proc = subprocess.run(cmd,timeout=3)
except subprocess.TimeoutExpired:
    print(???)

【问题讨论】:

  • 从 Python 3.5 开始,TimeoutExpired exception 似乎具有用于此目的的stdoutstderr 属性(假设您在调用run 时设置了capture_output=True)。但是,它目前似乎对我不起作用。

标签: python timeout subprocess output


【解决方案1】:

您需要使用Popensubprocess.PIPE 以便在超时到期时捕获进程输出。特别是Popen.communicate 是您所需要的。 这是一个例子

proc = subprocess.Popen(["ping", "192.168.1.1"],
                        stdout=subprocess.PIPE)

try:
    output, error = proc.communicate(timeout=2)
except subprocess.TimeoutExpired:
    proc.kill()
    output, error = proc.communicate()
    print(output)
    print(error)

这将打印到超时到期的进程输出。

【讨论】:

  • 感谢@Leonardo 的答案。我试过了,但它只打印命令而不是进程的输出:“Command '[..., ...]' timed out after 4 seconds”(就像您示例中的第二个输出行一样)。我想在子进程终止时打印它的输出。
  • @Ali_G 我找到了解决方案,请告诉我。
  • 这对我也不起作用...我认为问题出在@J.F. Sebastian 在其他一些帖子中(即link)。无论如何,谢谢!
【解决方案2】:

如果由于某种原因(一个是太旧的 python 版本)不能使用 timeout,这是我的解决方案,它适用于任何 python 版本:

  • 创建一个首先等待然后杀死subprocess对象的线程
  • 在主线程中,循环读取行。

我正在使用 python 子进程,使用 -u(无缓冲)选项运行:

transmitter.py:(每 1/10 秒打印“hello xx”的测试程序)

import time

i=0
while True:
    print("hello {}".format(i))
    i += 1
    time.sleep(0.1)

程序本身(超时设置为 1.5 秒):

import subprocess,threading,time

def timeout(p,timeout):
    time.sleep(timeout)
    p.kill()

p = subprocess.Popen(["python","-u","transmitter.py"],stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
t = threading.Thread(target=timeout,args=(p,1.5))
t.start()
output = []
for line in p.stdout:
    output.append(line.decode())

t.join()
print("".join(output))

最后,超时后,程序打印:

hello 0
hello 1
hello 2
hello 3
hello 4
hello 5
hello 6
hello 7
hello 8
hello 9
hello 10
hello 11
hello 12
hello 13
hello 14

【讨论】:

    【解决方案3】:

    这是为multiprocessing.Process捕获标准输出的方法

    import app
    import sys
    import io
    from multiprocessing import Process
    
    
    def run_app(some_param):
        sys.stdout = io.TextIOWrapper(open(sys.stdout.fileno(), 'wb', 0), write_through=True)
        app.run()
    
    app_process = Process(target=run_app, args=('some_param',))
    app_process.start()
    # Use app_process.termninate() for python <= 3.7.
    app_process.kill() 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-21
      • 2019-03-23
      • 1970-01-01
      • 2020-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多