我有一个函数,它有一个对象列表、两个int列表和一个int列表(一个ID(作为参数,它返回一个由两个int列表组成的元组。这个函数工作得很好,但当我的ID列表增加时,它会花费很多时间。在其他项目中已经使用了多处理,在我看来,这种情况适合使用多处理池。
然而,我在启动它时收到一个错误_pickle.PicklingError
。
在过去的几天里,我一直在寻找替代方法:我发现了pathos
ProcessPool
,它永远运行,没有任何问题迹象。我已经尝试过ThreadingPool
作为一个公认的答案,但它显然不适合我的问题,因为它不使用多个CPU,也没有加快进程。
这是我函数的一个例子,它不是一个可复制的例子,因为它是针对我的情况的。但我相信这个函数非常清楚:它返回在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 FilesJetBrainsPyCharm Community Edition 2021.2.2pluginspython-cehelperspydev_pydev_bundlepydev_umd.py", line 198, in runfile
pydev_imports.execfile(filename, global_vars, local_vars) # execute the script
File "C:Program FilesJetBrainsPyCharm Community Edition 2021.2.2pluginspython-cehelperspydev_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:ProgramDataAnaconda3envsmyenvlibmultiprocessingpool.py", line 290, in map
return self._map_async(func, iterable, mapstar, chunksize).get()
File "C:ProgramDataAnaconda3envsmyenvlibmultiprocessingpool.py", line 683, in get
raise self._value
File "C:ProgramDataAnaconda3envsmyenvlibmultiprocessingpool.py", line 457, in _handle_tasks
put(task)
File "C:ProgramDataAnaconda3envsmyenvlibmultiprocessingconnection.py", line 206, in send
self._send_bytes(_ForkingPickler.dumps(obj))
File "C:ProgramDataAnaconda3envsmyenvlibmultiprocessingreduction.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
,不会出现任何错误。