簡體   English   中英

Python多處理-發生未處理的異常時正常退出

[英]Python multiprocessing - graceful exit when an unhandled exception occurs

我的嘗試處理進程中異常的多處理程序的邏輯非常類似於以下內容:

import multiprocessing

class CriticalError(Exception):

    def __init__(self, error_message):
        print error_message
        q.put("exit")


def foo_process():
    while True:
        try:
            line = open("a_file_that_does_not_exist").readline()
        except IOError:
            raise CriticalError("IOError")

        try:
            text = line.split(',')[1]
            print text
        except IndexError:
            print 'no text'

if __name__ == "__main__":
    q = multiprocessing.Queue()
    p = multiprocessing.Process(target=foo_process)
    p.start()

    while True:
        if not q.empty():
            msg = q.get()
            if msg == "exit":
                p.terminate()
                exit()

如果我沒有關於文件操作的try-except,我會得到

Traceback (most recent call last):
  File "/usr/lib/python2.7/multiprocessing/process.py", line 258, in _bootstrap
    self.run()
  File "/usr/lib/python2.7/multiprocessing/process.py", line 114, in run
    self._target(*self._args, **self._kwargs)
  File "foo.py", line 22, in foo_process
    line = open("a_file_that_does_not_exist").readline()
IOError: [Errno 2] No such file or directory: 'a_file_that_does_not_exist'

但是該程序仍處於打開狀態。 是否有Python方式刪除與IOError相關的try-except子句,或者實際上使所有未處理的異常都將“退出”消息放入隊列“ q”,或終止進程並以其他方式退出程序? 當我不必捕獲沒有多處理的應用程序中的錯誤時,這將極大地清除我的代碼庫。 當AssertionError也將退出程序時,它還允許我添加斷言。 無論采用哪種解決方案,我都希望能夠看到回溯-我當前的解決方案不提供它。

由於孩子仍然會因異常而死亡(即p.terminate()是毫無意義的),那么為什么不讓主進程檢查其孩子是否還活着呢?

from queue import Empty
# from Queue import Empty  # if Python 2.x

while not q.empty():
    if not p.is_alive():
        break

    try:
        msg = q.get(timeout=1)
    except Empty:
        continue

    # other message handling code goes here

# some graceful cleanup
exit()

請注意,我在get上添加了超時,因此在孩子死后它不會永遠阻塞。 您可以根據需要自定義時間段。

這樣,您就不需要在子進程中執行任何異常操作,例如將錯誤推送到隊列中。 此外,原始方法在極少數情況下會失敗,例如,強行殺死孩子會導致主人永遠吊死(因為孩子沒有時間將任何東西推到隊列中)。

通過將foo_process函數內的sys.stdout (和/或sys.stderr )重新綁定(綁定到父級的stdout或文件或任何文件描述符支持的),可以潛在地從子進程中檢索回溯。 在這里看看:

多處理的日志輸出


沒有隊列並且有多個進程,我會選擇類似的東西:

processes = [f, b, c]
while processes:
    time.sleep(1)
    for p in processes:
        if not p.is_alive():
            processes.remove(p)
            break
exit()

使用join可以做得更好:

processes = [f, b, c]
for p in processes:
    p.join()
exit()

假設主人在等待孩子時不做任何其他事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM