不阻塞地轮询子进程对象

2024-04-27 03:40:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在编写一个python脚本,它在后台启动程序,然后监视程序是否遇到错误。我使用subprocess模块来启动进程并保留正在运行的程序的列表。在

processes.append((subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE), command))

我发现,当我试图通过对子进程对象调用communication来监视程序时,主程序会等待程序完成。我尝试过使用poll(),但这无法访问导致崩溃的错误代码,我希望解决此问题并重试打开进程。 runningProcesses是一个元组列表,其中包含subprocess对象和与之关联的命令。在

def monitorPrograms(runningProcesses):
    for program in runningProcesses:
        temp = program[0].communicate()
        if program[0].returncode:
            if program[0].returncode == 1:
                print "Program exited successfully."
            else:
                print "Whoops, something went wrong. Program %s crashed." % program[0].pid

当我试图在不使用communicate的情况下获取返回代码时,程序的崩溃没有注册。 我是必须使用线程来并行地运行通信,还是有一种更简单的方法我没有?在


Tags: 对象程序脚本列表if进程programcommand
2条回答

根据我的研究,最好的方法是使用线程。Here's an article我在创建自己的包以解决此问题时引用的。在

这里使用的基本方法是旋转不断请求子进程调用的日志输出(最后是退出状态)的线程。在

这是我自己的一个“接收者”的例子:

class Receiver(threading.Thread):
    def __init__(self, stream, stream_type=None, callback=None):
        super(Receiver, self).__init__()
        self.stream = stream
        self.stream_type = stream_type
        self.callback = callback
        self.complete = False
        self.text = ''

    def run(self):
        for line in iter(self.stream.readline, ''):
            line = line.rstrip()
            if self.callback:
                line = self.callback(line, msg_type=self.stream_type)
            self.text += line + "\n"
        self.complete = True

现在让接收器旋转的代码:

^{pr2}$

CommandOutput只是一个命名元组,它使引用我关心的数据变得容易。在

你会注意到我有一个“wait_for_complete”方法,它等待接收方将complete设置为True。一旦完成,execute方法调用流程.投票()以获取退出代码。现在我们有了所有的stdout/stderr和进程的状态代码。在

不需要使用线程来监视多个进程,特别是如果不使用它们的输出(使用^{} instead of ^{} to hide the output),请参见Python threading multiple bash subprocesses?

您的主要问题是Popen.poll()用法不正确。如果它返回None;这意味着进程仍在运行,您应该调用它,直到获得非None值。这是一个类似于你的案例code example that prints ^{} processes statuses。在

如果您确实想将子进程的stdout/stderr作为字符串获取,那么可以使用threads, async.io。在

如果您在Unix上,并且控制了可能产生子进程的所有代码,那么您可以避免轮询并自己处理SIGCHLDasynciostdlib库可以处理SIGCHLD。你也可以implement it manually, though it might be complicated。在

相关问题 更多 >