I want to submit a dynamically loaded functions to the concurrent.futures.ProcessPoolExecutor
. Here is the example. There is module.py
which contains the function.
# Content of module.py
def func():
return 1
And then, there is the rest in file.py
# Content of file.py
from concurrent.futures import ProcessPoolExecutor
import multiprocessing
import importlib
from pathlib import Path
import inspect
def load_function_from_module(path):
spec = importlib.util.spec_from_file_location(path.stem, str(path))
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)
return mod
def func_top_level():
return 2
if __name__ == '__main__':
# Dynamically load function from other module.
path = Path(__file__).parent / "module.py"
func = dict(inspect.getmembers(load_function_from_module(path)))["func"]
with ProcessPoolExecutor(2) as executor:
future = executor.submit(func)
future_ = executor.submit(func_top_level)
# Here comes the exception.
print(future.result())
The traceback is
Traceback (most recent call last):
_pickle.PicklingError: Can't pickle <function func at 0x7f5a548eb050>: it's not the same object as module.func
Solution 1: Wrapping func
with top-level function
Place def myfunc(): return func()
after the function is loaded and submit myfunc
.
This works for this example, but as soon as you move the whole if __name__ ...
block into its own main()
function, myfunc()
becomes local again and the hack does not work. Since the problem occurs deep down in my application, this is not possible.
Attempt 2: Replacing pickle
with cloudpickle
My personal favourite for a solution would be to change the way ProcessPoolExecutor
serializes objects. For example, cloudpickle
can serialize func
.
Although, this answer suggests that it is possible to register a custom reducer, the following PRs and issues suggest the feature does not work or I am just unable to replace pickle
with cloudpickle
.
- https://bugs.python.org/issue28053
- https://github.com/python/cpython/pull/9959
- https://github.com/python/cpython/pull/15058
Thank you very much for your help.