使用Python的Popen,多处理和守护进程

时间:2014-09-30 13:17:13

标签: python multiprocessing subprocess popen python-multiprocessing

我需要使用 Popen 运行一个长 foobar.py 进程,并使用多处理进程解析其输出。

我的问题是有时我不能等待解析器完成,所以我需要使用the multiprocessing daemon property守护解析器。我需要解析器可以使用两种非语言的非守护进程方式。该文档还说守护进程不允许创建子进程。所以在这种情况下,我在解析器分叉之前运行Popen进程(参见下面的start方法)。

class Parser(multiprocessing.Process):
    def __init__(self, daemon, output):
        super(Parser, self).__init__()
        self.daemon = daemon
        self.output = output

    def start(self):
        if self.daemon:
            self.launchFoobar() # Foobar is launched before forking
        super(Parser, self).start()

    def run(self):
        if not self.daemon:
            self.launchFoobar() # Foobar is launched after forking
        self.parseFoobar()

    def launchFoobar(self):
        self.process = subprocess.Popen(["python", "foobar.py"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

    def parseFoobar(self):
        with open(self.output, "w+") as f:
            for line in iter(self.process.stdout):
                f.write(line)
                f.flush()
        self.process.wait()

我们这里说foobar.py等待几秒钟并打印一些内容,而 parseFoobar 方法只是在文件中输出输出。在我看来,这两个函数都比这复杂得多。

正常运行Parser(daemon=False, "sync.txt").start()并且 sync.txt 中有一些输出。但是,运行Parser(daemon=True, "async.txt")不会在 async.txt 中生成任何内容,并且似乎在第for line in iter(self.process.stdout):行被阻止,因为该文件已创建,但它是空的。

为什么不起作用?我该如何解决?

您可以找到parser.pyfoobar.py的要点进行测试。只需运行python parser.py并查看输出文件。

修改:django daemonize methods

中有一些提示

1 个答案:

答案 0 :(得分:3)

您实际上正在获得所需的确切行为。您正在创建守护程序Process,然后几乎立即退出主进程。这并没有给守护进程Process足够的时间来实际执行foobar.py并在终止之前解析其输出。如果您在程序结束时添加了对async.join()的调用,则会看到async.txt已写入。

另请注意,可以从守护程序subprocess.Popen内部调用multiprocessing.Process。关于daemon进程无法创建子进程的说明实际上只是讨论创建子multiprocessing.Process对象。之所以有限制是因为守护程序Process无法正确清理子Process个对象,但subprocess.Popen打开的进程无法清除无论如何,父母退出了。