Custom exceptions are not raised properly when used in Multiprocessing Pool Custom exceptions are not raised properly when used in Multiprocessing Pool python-3.x python-3.x

Custom exceptions are not raised properly when used in Multiprocessing Pool


The issue is that your exception classes have non-optional arguments in their __init__ methods, but that when you call the superclass __init__ method you don't pass those arguments along. This causes a new exception when your exception instances are unpickled by the multiprocessing code.

This has been a long-standing issue with Python exceptions, and you can read quite a bit of the history of the issue in this bug report (in which a part of the underlying issue with pickling exceptions was fixed, but not the part you're hitting).

To summarize the issue: Python's base Exception class puts all the arguments it's __init__ method receives into an attribute named args. Those arguments are put into the pickle data and when the stream is unpickled, they're passed to the __init__ method of the newly created object. If the number of arguments received by Exception.__init__ is not the same as a child class expects, you'll get at error at unpickling time.

A workaround for the issue is to pass all the arguments you custom exception classes require in their __init__ methods to the superclass __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)

Another possible fix would be to not call the superclass __init__ method at all (this is what the fix in the bug linked above allows), but since that's usually poor behavior for a subclass, I can't really recommend it.


Your ModuleException_2.__init__ fails while beeing unpickled.

I was able to fix the problem by changing the signature to

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

but better have a look at Pickling Class Instances to ensure a clean implementation.