簡體   English   中英

在python中運行子進程並獲取stdout並在超時時終止進程

[英]Run subprocess in python and get stdout and kill process on timeout

這是我的代碼,它啟動一個子進程,等到它結束並返回stdout,或者發生超時並引發異常。 常用的是print(Run('python --version').execute())

class Run(object):
    def __init__(self, cmd, timeout=2*60*60):
        self.cmd = cmd.split()
        self.timeout = timeout
        self._stdout = b''
        self.dt = 10
        self.p = None

    def execute(self):
        print("Execute command: {}".format(' '.join(self.cmd)))

        def target():
            self.p = Popen(self.cmd, stdout=PIPE, stderr=STDOUT)
            self._stdout = self.p.communicate()[0]

        thread = Thread(target=target)
        thread.start()

        t = 0
        while t < self.timeout:
            thread.join(self.dt)
            if thread.is_alive():
                t += self.dt
                print("Running for: {} seconds".format(t))
            else:
                ret_code = self.p.poll()
                if ret_code:
                    raise AssertionError("{} failed.\nretcode={}\nstdout:\n{}".format(
                        self.cmd, ret_code, self._stdout))
                return self._stdout

        else:
            print('Timeout {} reached, kill task, pid={}'.format(self.timeout, self.p.pid))
            self.p.terminate()
            thread.join()
            raise AssertionError("Timeout")

問題是以下情況。 我啟動的進程產生了更多的子進程。 因此,當達到超時時,我使用self.p.terminate()殺死了主進程(使用我的班級淘汰的那個主進程self.p.terminate() ,子self.p.terminate()仍然存在,我的代碼掛在了self._stdout = self.p.communicate()[0] 如果我手動終止所有子進程,執行將繼續。

當我殺死整個進程樹而不是self.p.terminate()時,我嘗試了解決方案。

如果主要過程本身及其子項獨立存在,並且我也沒有找到並殺死它們的能力,那么這也不起作用。 但是它們阻止了self.p.communicate()

有辦法有效解決這個問題嗎?

您可以使用PySys框架中的ProcessWrapper-它以跨平台的方式提供了很多作為抽象的功能,即

import sys, os
from pysys.constants import *
from pysys.process.helper import ProcessWrapper
from pysys.exceptions import ProcessTimeout

command=sys.executable
arguments=['--version']
try:
    process = ProcessWrapper(command, arguments=arguments, environs=os.environ, workingDir=os.getcwd(), stdout='stdout.log', stderr='stderr.log', state=FOREGROUND, timeout=5.0)
    process.start()
except ProcessTimeout:
    print "Process timeout"
    process.stop()

如果感興趣的話,可以在SourceForge( http://sourceforge.net/projects/pysys/files/http://pysys.sourceforge.net/ )上找到。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM