我需要使用 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.py和foobar.py的要点进行测试。只需运行python parser.py
并查看输出文件。
答案 0 :(得分:3)
您实际上正在获得所需的确切行为。您正在创建守护程序Process
,然后几乎立即退出主进程。这并没有给守护进程Process
足够的时间来实际执行foobar.py
并在终止之前解析其输出。如果您在程序结束时添加了对async.join()
的调用,则会看到async.txt
已写入。
另请注意,可以从守护程序subprocess.Popen
内部调用multiprocessing.Process
。关于daemon
进程无法创建子进程的说明实际上只是讨论创建子multiprocessing.Process
对象。之所以有限制是因为守护程序Process
无法正确清理子Process
个对象,但subprocess.Popen
打开的进程无法清除无论如何,父母退出了。