我在尝试使用多处理时遇到了一个错误,我认为读取其他线程与python中的一些对象不可拾取有关。然而,在我在网上发现的所有这种错误的例子中,人们都试图将这些对象作为多处理中使用的函数中的参数来传递。在我的情况下,我只需要这个对象来加载我要处理的数据。我创建了一个看起来像这样的最小示例:
import multiprocessing
from test import Foo
def test(x):
return x**2
def load():
foo = Foo(analysis_folder)
del foo
load()
pool = multiprocessing.Pool(8)
print(list(pool.map(test, range(10))))
你可以看到,我甚至没有从load函数返回任何东西,我甚至试图从内存中删除foo对象。多处理中使用的测试函数只能用int调用。然而,我仍然得到这个错误:
Traceback (most recent call last):
File "test.py", line 17, in <module>
print(list(pool.map(test, range(10))))
File "/opt/tljh/user/lib/python3.7/multiprocessing/pool.py", line 268, in map
return self._map_async(func, iterable, mapstar, chunksize).get()
File "/opt/tljh/user/lib/python3.7/multiprocessing/pool.py", line 657, in get
raise self._value
File "/opt/tljh/user/lib/python3.7/multiprocessing/pool.py", line 431, in _handle_tasks
put(task)
File "/opt/tljh/user/lib/python3.7/multiprocessing/connection.py", line 206, in send
self._send_bytes(_ForkingPickler.dumps(obj))
File "/opt/tljh/user/lib/python3.7/multiprocessing/reduction.py", line 51, in dumps
cls(buf, protocol).dump(obj)
_pickle.PicklingError: Can't pickle <function test at 0x7f2c368881e0>: attribute lookup test on __main__ failed
对加载函数的调用被注释掉后,一切都如预期一样工作:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
我有什么办法可以防止这种情况发生吗?我尝试在最后3行之前添加if __name__ == '__main__':
,但仍然出现错误。我不明白为什么调用load((函数会突然使test((无法被pickle。
您需要这样做:
def main():
load()
pool = multiprocessing.Pool(8)
print(list(pool.map(test, range(10))))
if __name__ == "__main__":
main()
尽管这在任何时候都是一种很好的做法,但对于多处理来说尤其重要。记住,第二个进程必须重新加载第一个进程中的所有模块。当它重新加载主模块时,它将再次运行所有代码。
使用真实答案编辑
好吧,我终于看到问题了。问题是,您有一个名为";测试";以及一个称为";测试";。当文件在另一个模块中重新加载时,from test import foo
正试图从您的函数中导入一些内容。这导致Python爆炸。更改模块或更改函数名称。