2

我需要與POPEN運行長foobar.py過程和解析其輸出與多處理過程。POPEN,多和守護程序與Python

我的問題是,有時我不能等待解析器完成,所以我需要使用the multiprocessing daemon property對解析器進行守護進程。我需要解析器可以使用deamonic non daemonic方式。該文檔還表示,一個守護進程不允許創建子進程。所以在這種情況下,我會在解析器分叉之前運行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

回答

2

一些提示,你實際上得到你想要的確切行爲。您正在創建一個守護進程Process,然後幾乎立即退出主進程。這不會使守護進程Process有足夠的時間來實際執行foobar.py並在其終止之前解析其輸出。如果在程序結尾處添加對async.join()的呼叫,您將看到async.txt確實被寫入。

另請注意,您可以從multiprocessing.Process內部的可以調用subprocess.Popen。關於daemon進程無法創建子進程的說明實際上只是在討論如何創建子對象。限制在那裏,因爲守護進程Process將無法​​正確清理子對象Process,但打開的進程subprocess.Popen在父進程退出時無法清理。

+0

如果最後調用join(),創建守護進程的意義何在?在這種情況下,我需要創建過程並忘記它。解析器很有可能會死在父代之後。 – azmeuk 2014-09-30 13:52:27

+0

@azmeuk這很好,那麼你可以做到這一點。但是有時守護進程'Process'不會完成你期望的工作。在這種情況下,父進程在能夠解析foobar.py的輸出之前正在退出。 – dano 2014-09-30 13:53:49

+0

@azmeuk我會說一般情況下,將一個守護進程'進程'寫入文件是非常危險的,因爲如果守護進程在寫入文件的過程中突然終止,該文件可能很容易以損壞的狀態結束。 – dano 2014-09-30 13:55:16