gpt4 book ai didi

python - 在多处理池中使用时未正确引发自定义异常

转载 作者:太空狗 更新时间:2023-10-29 22:11:09 28 4
gpt4 key购买 nike

问题

我正在观察 Python 3.3.4 中的行为,我想帮助理解:为什么我的异常在函数正常执行时正确引发,但在函数在工作池中执行时却没有?

代码

import multiprocessing

class AllModuleExceptions(Exception):
"""Base class for library exceptions"""
pass

class ModuleException_1(AllModuleExceptions):
def __init__(self, message1):
super(ModuleException_1, self).__init__()
self.e_string = "Message: {}".format(message1)
return

class ModuleException_2(AllModuleExceptions):
def __init__(self, message2):
super(ModuleException_2, self).__init__()
self.e_string = "Message: {}".format(message2)
return

def func_that_raises_exception(arg1, arg2):
result = arg1 + arg2
raise ModuleException_1("Something bad happened")

def func(arg1, arg2):

try:
result = func_that_raises_exception(arg1, arg2)

except ModuleException_1:
raise ModuleException_2("We need to halt main") from None

return result

pool = multiprocessing.Pool(2)
results = pool.starmap(func, [(1,2), (3,4)])

pool.close()
pool.join()

print(results)

此代码产生此错误:

Exception in thread Thread-3:
Traceback (most recent call last):
   File "/user/peteoss/encap/Python-3.4.2/lib/python3.4/threading.py", line 921, in _bootstrap_inner
    self.run()  
File "/user/peteoss/encap/Python-3.4.2/lib/python3.4/threading.py", line 869, in run
    self._target(*self._args, **self._kwargs)
  File "/user/peteoss/encap/Python-3.4.2/lib/python3.4/multiprocessing/pool.py", line 420, in _handle_results
    task = get()
  File "/user/peteoss/encap/Python-3.4.2/lib/python3.4/multiprocessing/connection.py", line 251, in recv
    return ForkingPickler.loads(buf.getbuffer()) TypeError: __init__() missing 1 required positional argument: 'message2'

相反,如果我简单地调用该函数,它似乎可以正确处理异常:

print(func(1, 2))

产生:

Traceback (most recent call last):
  File "exceptions.py", line 40, in
    print(func(1, 2))
  File "exceptions.py", line 30, in func
    raise ModuleException_2("We need to halt main") from None
__main__.ModuleException_2

为什么 ModuleException_2 在进程池中运行时表现不同?

最佳答案

问题是您的异常类在它们的 __init__ 方法中有非可选参数,但是当您调用父类(super class) __init__ 方法时,您不会传递这些参数沿着。当您的异常实例被 multiprocessing 代码解封时,这会导致新的异常。

这是 Python 异常的一个长期存在的问题,您可以在 this bug report 中阅读相当多的问题历史记录。 (其中修复了酸洗异常的部分潜在问题,但不是您遇到的部分)。

总结一下这个问题:Python 的基 Exception 类将它的 __init__ 方法接收的所有参数放入一个名为 args 的属性中。这些参数被放入 pickle 数据中,当流被 unpickle 时,它​​们被传递给新创建对象的 __init__ 方法。如果 Exception.__init__ 接收到的参数数量与子类期望的数量不同,您将在 unpickling 时出错。

该问题的解决方法是将自定义异常类在其 __init__ 方法中所需的所有参数传递给父类(super class) __init__:

class ModuleException_2(AllModuleExceptions):
def __init__(self, message2):
super(ModuleException_2, self).__init__(message2) # the change is here!
self.e_string = "Message: {}".format(message2)

另一种可能的修复方法是根本不调用父类(super class) __init__ 方法(这是上面链接的错误中允许的修复方法),但由于这通常是子类的不良行为,我可以真的很推荐。

关于python - 在多处理池中使用时未正确引发自定义异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27993567/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com