首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python多处理-在发生未处理异常时优雅退出

Python多处理-在发生未处理异常时优雅退出
EN

Stack Overflow用户
提问于 2016-08-10 13:50:59
回答 1查看 1.7K关注 0票数 0

我的多处理程序试图处理进程中的异常的逻辑非常类似于以下内容:

代码语言:javascript
复制
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()

如果我没有尝试-除了关于文件的操作,我得到

代码语言:javascript
复制
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'

但这个项目仍然开放。是否有一种Pythonic方法来删除与IOError相关的try-以外子句,或者实际上,所有未处理的异常要么将" exit“消息放入队列'q',要么以其他方式终止进程并退出程序?这将清除大量我的代码库,当我不需要捕获那些在没有多处理的应用程序中自动杀死程序的错误时。它还允许我在AssertionError退出程序时添加断言。不管是什么解决方案,我都希望能够看到回溯--我目前的解决方案并没有提供它。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-08-10 14:06:48

既然子进程无论如何都会因异常而死亡(即p.terminate()是没有意义的),那么为什么不让主进程检查它的子进程是否还活着呢?

代码语言:javascript
复制
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上添加了超时,这样在子节点死后它不会永远阻塞。您可以根据需要自定义期间。

这样,您就不需要在子进程中执行任何不寻常的操作,比如错误时将队列推送到队列中。此外,在一些罕见的情况下,最初的方法将失败,例如,强制杀死孩子会导致主人永远挂起(因为孩子没有时间把任何东西推到队列中)。

您可以通过将sys.stdout (和/或sys.stderr)重新绑定到foo_process函数内(到父进程或文件或任何文件描述符支持的文件)中,从子进程检索追溯。看看这里:

Log output of multiprocessing.Process

如果没有队列,并且有多个进程,我就会这样做:

代码语言:javascript
复制
processes = [f, b, c]
while processes:
    time.sleep(1)
    for p in processes:
        if not p.is_alive():
            processes.remove(p)
            break
exit()

通过联接可以做得更好:

代码语言:javascript
复制
processes = [f, b, c]
for p in processes:
    p.join()
exit()

假设主人在等孩子的时候不应该做任何其他事情。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38875378

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档