Python multiprocessing - 发生未处理的异常时从容退出
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'
但该计划仍然开放。有没有一种 Pythonic 的方法来删除 try-except
与 IOError 相关的子句,或者实际上,所有未处理的异常
将 "exit" 消息放入队列 'q',或者终止进程并退出
以其他方式编程?当我
不必捕获在没有多处理的应用程序中自动终止程序的错误。
它还允许我在 AssertionError 也会添加断言时添加断言
退出程序。无论采用何种解决方案,我都希望能够看到
追溯——我目前的解决方案没有提供它。
既然 child 无论如何都会死于异常(即 p.terminate()
毫无意义)那么为什么不让主进程检查它的 child 是否还活着呢?
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
上添加了超时,因此当 child 已死时它不会永远阻塞。您可以根据需要自定义时间段。
有了它,您不需要在 child 过程中做任何不寻常的事情,比如在出错时推送到队列。除了原始方法在极少数情况下会失败,例如在 child 上强制终止将导致 master 永远挂起(因为 child 没有时间将任何东西推送到队列)。
您可以通过在 foo_process
函数(到 parent 的 stdout
或文件或任何文件描述符支持)。看看这里:
Log output of multiprocessing.Process
如果没有队列和多个进程,我会做类似的事情:
processes = [f, b, c]
while processes:
time.sleep(1)
for p in processes:
if not p.is_alive():
processes.remove(p)
break
exit()
连接可以做得更好:
processes = [f, b, c]
for p in processes:
p.join()
exit()
假设 master 在等待 children 时不应该做任何其他事情。
我的多处理程序试图处理进程中的异常的逻辑与以下内容非常相似:
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'
但该计划仍然开放。有没有一种 Pythonic 的方法来删除 try-except 与 IOError 相关的子句,或者实际上,所有未处理的异常 将 "exit" 消息放入队列 'q',或者终止进程并退出 以其他方式编程?当我 不必捕获在没有多处理的应用程序中自动终止程序的错误。 它还允许我在 AssertionError 也会添加断言时添加断言 退出程序。无论采用何种解决方案,我都希望能够看到 追溯——我目前的解决方案没有提供它。
既然 child 无论如何都会死于异常(即 p.terminate()
毫无意义)那么为什么不让主进程检查它的 child 是否还活着呢?
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
上添加了超时,因此当 child 已死时它不会永远阻塞。您可以根据需要自定义时间段。
有了它,您不需要在 child 过程中做任何不寻常的事情,比如在出错时推送到队列。除了原始方法在极少数情况下会失败,例如在 child 上强制终止将导致 master 永远挂起(因为 child 没有时间将任何东西推送到队列)。
您可以通过在 foo_process
函数(到 parent 的 stdout
或文件或任何文件描述符支持)。看看这里:
Log output of multiprocessing.Process
如果没有队列和多个进程,我会做类似的事情:
processes = [f, b, c]
while processes:
time.sleep(1)
for p in processes:
if not p.is_alive():
processes.remove(p)
break
exit()
连接可以做得更好:
processes = [f, b, c]
for p in processes:
p.join()
exit()
假设 master 在等待 children 时不应该做任何其他事情。