gpt4 book ai didi

python - cProfile 在运行多处理 Python 代码时导致 pickle 错误

转载 作者:行者123 更新时间:2023-12-03 10:08:18 25 4
gpt4 key购买 nike

我有一个 Python 脚本在我正常运行时运行良好:
$ python script.py <options>
我正在尝试使用 cProfile 模块分析代码:
$ python -m cProfile -o script.prof script.py <options>
当我启动上述命令时,我收到一个关于无法 pickle 函数的错误:

Traceback (most recent call last):
File "scripts/process_grid.py", line 1500, in <module>
_compute_write_index(kwrgs)
File "scripts/process_grid.py", line 626, in _compute_write_index
args,
File "scripts/process_grid.py", line 1034, in _parallel_process
pool.map(_apply_along_axis_palmers, chunk_params)
File "/home/james/miniconda3/envs/climate/lib/python3.6/multiprocessing/pool.py", line 266, in map
return self._map_async(func, iterable, mapstar, chunksize).get()
File "/home/james/miniconda3/envs/climate/lib/python3.6/multiprocessing/pool.py", line 644, in get
raise self._value
File "/home/james/miniconda3/envs/climate/lib/python3.6/multiprocessing/pool.py", line 424, in _handle_tasks
put(task)
File "/home/james/miniconda3/envs/climate/lib/python3.6/multiprocessing/connection.py", line 206, in send
self._send_bytes(_ForkingPickler.dumps(obj))
File "/home/james/miniconda3/envs/climate/lib/python3.6/multiprocessing/reduction.py", line 51, in dumps
cls(buf, protocol).dump(obj)
_pickle.PicklingError: Can't pickle <function _apply_along_axis_palmers at 0x7fe05a540b70>: attribute lookup _apply_along_axis_palmers on __main__ failed

该代码使用多处理,我假设这是进行 pickle 的地方。

游戏中的代码是 here on GitHub .

本质上,我在进程池中映射一个函数和一个相应的参数字典:
pool.map(_apply_along_axis_palmers, chunk_params)
函数 _apply_along_axis_palmers据我所知,它是“可 pickle 的”,因为它是在模块的顶层定义的。同样,在 cProfile 上下文之外运行时不会发生此错误,所以这可能为 pickle 添加了额外的约束?

任何人都可以评论为什么会发生这种情况,和/或我如何纠正这个问题?

最佳答案

你在这里遇到的问题是,通过使用 -mcProfile ,模块__main__cProfile (代码的实际入口点),而不是您的脚本。 cProfile尝试通过确保脚本运行时看到 __name__ 来解决此问题如"__main__" , 所以它知道它是作为脚本运行的,而不是作为模块导入的,而是 sys.modules['__main__']仍然是 cProfile模块。
问题是,pickle仅通过 pickle 它们的限定名称来处理 pickle 函数(加上一些样板文件,首先说它是一个函数)。并且为了确保它能够在往返过程中存活,它总是会仔细检查是否可以在 sys.modules 中查找限定名称。 .所以当你做 pickle.dumps(_apply_along_axis_palmers) (在这种情况下通过将其作为映射器函数显式或隐式传递),其中 _apply_along_axis_palmers在您的主脚本中定义,它会仔细检查 sys.modules['__main__']._apply_along_axis_palmers存在。但事实并非如此,因为 cProfile._apply_along_axis_palmers不存在。
我不知道有什么好的解决方案。我能想到的最好办法是手动修复 sys.modules使其正确公开您的模块及其内容。我还没有完全测试过,所以可能会有一些怪癖,但我找到的解决方案是更改名为 mymodule.py 的模块形式:

# imports...
# function/class/global defs...

if __name__ == '__main__':
main() # Or series of statements
到:
# imports...
import sys
# function/class/global defs...

if __name__ == '__main__':
import cProfile
# if check avoids hackery when not profiling
# Optional; hackery *seems* to work fine even when not profiling, it's just wasteful
if sys.modules['__main__'].__file__ == cProfile.__file__:
import mymodule # Imports you again (does *not* use cache or execute as __main__)
globals().update(vars(mymodule)) # Replaces current contents with newly imported stuff
sys.modules['__main__'] = mymodule # Ensures pickle lookups on __main__ find matching version
main() # Or series of statements
从那里开始, sys.modules['__main__']指您自己的模块,而不是 cProfile ,所以事情似乎奏效了。 cProfile尽管如此,似乎仍然有效,并且 pickle 可以按预期找到您的功能。只有真正的成本是重新导入你的模块,但如果你做了足够多的实际工作,重新导入的成本应该相当小。

关于python - cProfile 在运行多处理 Python 代码时导致 pickle 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53890693/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com