PicklingError : What can cause this error in a function?
PicklingError : What can cause this error in a function?
我有一个函数,其中包含一个 对象列表 、两个 整数列表 和一个 int(一个ID)作为参数,其中returns两个int列表的元组。这个功能很好用,但是当我的 ID 列表变长时,它会花费很多时间。已经在其他项目中使用过multiprocessing,在我看来,这种情况适合使用multiprocessing Pool。
但是,我在启动时遇到错误 _pickle.PicklingError
。
过去几天我一直在寻找替代方法:我发现 pathos
ProcessPool
永远运行,没有任何问题迹象。我已经尝试 ThreadingPool
作为已接受的答案,但它显然不适合我的问题,因为它不使用多个 CPU 并且不会加快进程。
这是我的函数示例,它不是可重现的示例,因为它是针对我的情况的。但我相信该功能非常清楚:它 returns 两个列表的元组,在 for 循环中创建。
def getNormalOnConnectedElements(elem, mapping, idList, node):
normalZ = []
eids = []
for e in mapping[node]:
if e in idList:
normalZ.append(elem[e].Normal()[2])
eids.append(e)
return normalZ, eids
我试着像往常一样调用它:
with Pool(4) as p:
# with functools.partial()
result = p.map(partial(getNormalOnConnectedElements, elemList, mapping, idList), nodeList)
# or with itertools.repeat()
result = p.starmap(getNormalOnConnectedElements, zip(repeat(elemList), repeat(mapping), repeat(idList), nodeList))
我确保函数是在顶层定义的,并且调用在 if __name__ == "__main__":
块中。
所以问题是:这个函数中的什么导致 pickle 抛出 _pickle.PicklingError
?
编辑:
File "<input>", line 1, in <module>
File "C:\Program Files\JetBrains\PyCharm Community Edition 2021.2.2\plugins\python-ce\helpers\pydev\_pydev_bundle\pydev_umd.py", line 198, in runfile
pydev_imports.execfile(filename, global_vars, local_vars) # execute the script
File "C:\Program Files\JetBrains\PyCharm Community Edition 2021.2.2\plugins\python-ce\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile
exec(compile(contents+"\n", file, 'exec'), glob, loc)
File "C:/Users/TLEP6OQM/Documents/Anaconda/PLoad tool/model.py", line 209, in <module>
allVec = p.map(partial(getNormalOnConnectedElements, elem, allElemIds, mapping), myFilter)
File "C:\ProgramData\Anaconda3\envs\myenv\lib\multiprocessing\pool.py", line 290, in map
return self._map_async(func, iterable, mapstar, chunksize).get()
File "C:\ProgramData\Anaconda3\envs\myenv\lib\multiprocessing\pool.py", line 683, in get
raise self._value
File "C:\ProgramData\Anaconda3\envs\myenv\lib\multiprocessing\pool.py", line 457, in _handle_tasks
put(task)
File "C:\ProgramData\Anaconda3\envs\myenv\lib\multiprocessing\connection.py", line 206, in send
self._send_bytes(_ForkingPickler.dumps(obj))
File "C:\ProgramData\Anaconda3\envs\myenv\lib\multiprocessing\reduction.py", line 51, in dumps
cls(buf, protocol).dump(obj)
_pickle.PicklingError: Can't pickle <function getNormalOnConnectedElements at 0x00000257E6785620>: attribute lookup getNormalOnConnectedElements on __main__ failed
如果有人偶然发现了这个问题,即使使用非常简单的函数也会发生此错误的原因是因为我 运行 使用 python 脚本的方式。正如 ShadowRanger 在评论中很好地解释的那样,该函数需要在顶层定义。在 PyCharm 中,“运行 Python 控制台中的文件”不只是 运行 它,而是包装了它。
通过 运行 以正确的方式打开文件,或调用 python myscript.py
,没有出现错误。
我有一个函数,其中包含一个 对象列表 、两个 整数列表 和一个 int(一个ID)作为参数,其中returns两个int列表的元组。这个功能很好用,但是当我的 ID 列表变长时,它会花费很多时间。已经在其他项目中使用过multiprocessing,在我看来,这种情况适合使用multiprocessing Pool。
但是,我在启动时遇到错误 _pickle.PicklingError
。
过去几天我一直在寻找替代方法:我发现 pathos
ProcessPool
永远运行,没有任何问题迹象。我已经尝试 ThreadingPool
作为已接受的答案,但它显然不适合我的问题,因为它不使用多个 CPU 并且不会加快进程。
这是我的函数示例,它不是可重现的示例,因为它是针对我的情况的。但我相信该功能非常清楚:它 returns 两个列表的元组,在 for 循环中创建。
def getNormalOnConnectedElements(elem, mapping, idList, node):
normalZ = []
eids = []
for e in mapping[node]:
if e in idList:
normalZ.append(elem[e].Normal()[2])
eids.append(e)
return normalZ, eids
我试着像往常一样调用它:
with Pool(4) as p:
# with functools.partial()
result = p.map(partial(getNormalOnConnectedElements, elemList, mapping, idList), nodeList)
# or with itertools.repeat()
result = p.starmap(getNormalOnConnectedElements, zip(repeat(elemList), repeat(mapping), repeat(idList), nodeList))
我确保函数是在顶层定义的,并且调用在 if __name__ == "__main__":
块中。
所以问题是:这个函数中的什么导致 pickle 抛出 _pickle.PicklingError
?
编辑:
File "<input>", line 1, in <module>
File "C:\Program Files\JetBrains\PyCharm Community Edition 2021.2.2\plugins\python-ce\helpers\pydev\_pydev_bundle\pydev_umd.py", line 198, in runfile
pydev_imports.execfile(filename, global_vars, local_vars) # execute the script
File "C:\Program Files\JetBrains\PyCharm Community Edition 2021.2.2\plugins\python-ce\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile
exec(compile(contents+"\n", file, 'exec'), glob, loc)
File "C:/Users/TLEP6OQM/Documents/Anaconda/PLoad tool/model.py", line 209, in <module>
allVec = p.map(partial(getNormalOnConnectedElements, elem, allElemIds, mapping), myFilter)
File "C:\ProgramData\Anaconda3\envs\myenv\lib\multiprocessing\pool.py", line 290, in map
return self._map_async(func, iterable, mapstar, chunksize).get()
File "C:\ProgramData\Anaconda3\envs\myenv\lib\multiprocessing\pool.py", line 683, in get
raise self._value
File "C:\ProgramData\Anaconda3\envs\myenv\lib\multiprocessing\pool.py", line 457, in _handle_tasks
put(task)
File "C:\ProgramData\Anaconda3\envs\myenv\lib\multiprocessing\connection.py", line 206, in send
self._send_bytes(_ForkingPickler.dumps(obj))
File "C:\ProgramData\Anaconda3\envs\myenv\lib\multiprocessing\reduction.py", line 51, in dumps
cls(buf, protocol).dump(obj)
_pickle.PicklingError: Can't pickle <function getNormalOnConnectedElements at 0x00000257E6785620>: attribute lookup getNormalOnConnectedElements on __main__ failed
如果有人偶然发现了这个问题,即使使用非常简单的函数也会发生此错误的原因是因为我 运行 使用 python 脚本的方式。正如 ShadowRanger 在评论中很好地解释的那样,该函数需要在顶层定义。在 PyCharm 中,“运行 Python 控制台中的文件”不只是 运行 它,而是包装了它。
通过 运行 以正确的方式打开文件,或调用 python myscript.py
,没有出现错误。