【问题标题】:Popen, multiprocessing and daemons with Python使用 Python 的 Popen、多处理和守护进程
【发布时间】:2014-11-25 03:24:33
【问题描述】:

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

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

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中有一些提示

【问题讨论】:

    标签: python multiprocessing subprocess popen python-multiprocessing


    【解决方案1】:

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

    还请注意,您可以从守护进程multiprocessing.Process 内部调用subprocess.Popen。关于daemon 进程无法创建子进程的注释实际上只是在谈论创建子multiprocessing.Process 对象。存在限制是因为守护进程 Process 将无法正确清理子 Process 对象,但由 subprocess.Popen 打开的进程在父进程退出时不会被清理。

    【讨论】:

    • 如果最后调用join(),创建守护进程有什么意义?在这种情况下,我需要创建流程并忘记它。解析器很可能在它的父节点之后死掉。
    • @azmeuk 没关系,那么你可以这样做。但是有时守护进程Process 不会完成您期望的工作。在这种情况下,父进程在 Process 可以解析 foobar.py 的输出之前退出。
    • @azmeuk 我会说,一般来说,让守护进程Process 写入文件实际上是很危险的,因为如果守护进程在正在写它。
    • 守护进程的原理是它可以在它的父进程中存活,我错了吗?那样的话怎么会突然终止呢?
    • @azmeuk 不,守护进程multiprocessing.Process 对象在父进程退出后立即终止。他们的寿命不会超过父母的一生。 multiprocesing.Processthreading.Thread 非常相似;守护进程Thread 不能超过其父进程的生命周期,所以 multiprocessing.Process 也不能。
    猜你喜欢
    • 2023-03-10
    • 1970-01-01
    • 2011-09-19
    • 1970-01-01
    • 2017-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多