python - ProcessPoolExecutor:TypeError:无法腌制“PyCapsule”对象
问题描述
我正面临concurrent.futures
's的问题ProcessPoolExecutor
,我正试图在我的课程中使用它:
def __init__():
self._pool = ProcessPoolExecutor()
def handle_event():
...
filepath: Path = xxxx
future = self._pool.submit(self.test, filepath)
res = future.result()
self.logger.debug(res)
def test(self, filepath: Path):
print("Test ProcessPoolExecutor")
return 3
这个小代码有一个奇怪的行为。首先,当我删除获取结果时,我在函数future.result()
中看不到我的print
消息输出。test()
然后,当我明确要求未来的结果时,我得到一个TypeError
:
Traceback (most recent call last):
File "/usr/lib/python3.8/multiprocessing/queues.py", line 239, in _feed
obj = _ForkingPickler.dumps(obj)
File "/usr/lib/python3.8/multiprocessing/reduction.py", line 51, in dumps
cls(buf, protocol).dump(obj)
TypeError: cannot pickle 'PyCapsule' object
我在这里不明白的是,我发送(
Path
)和接收(int
)的类型都是 Picklable。其次,我什至不知道这个 PyCapsule 依赖项是什么,因为它没有出现在我的
requirements.txt
,也没有出现在pip freeze
(相关的 SO 帖子)中
.nox/run/bin/pip freeze | grep -E '(capsule|dill)'
知道为什么我看不到我的打印语句出现吗?PyCapsule 错误呢?是我的类型有问题,还是应用程序中的其他地方有问题?
谢谢 !
解决方案
在为您安排作业时,concurrent.futures.ProcessPoolExecutor
会同时发送函数名称和参数。子进程接收函数名称并在其内存中查找它。
当您传递一个对象方法时,事情变得更加复杂。子进程在其函数中找不到这样的方法。因此,父母必须腌制和运送整个对象。
这是您遇到问题的地方:
cls(buf, protocol).dump(obj)
pickle 协议不知道如何序列化您的对象,因为它包含不可提取的组件。特别是,PyCapsule是一种内部 Python 数据结构。
建议不要将对象方法传递给进程池,因为很难预测对象是否可腌制。此外,您还要支付序列化整个对象并通过管道传输它而不是仅仅传送函数名称的增加成本。
有关什么容易腌制和什么不容易腌制的更多信息,您可以参考其模块文档。
如果您不能遵守上述建议,您可以查看其他 pickle 实现,例如dill。
推荐阅读
- css - 是否可以使用带有标签的媒体查询,例如?
- linux - 在 Linux 中使用信号量的有界缓冲区问题
- angular - MSAL/Angular - 间歇性令牌似乎过时并且 msal 构造了不正确的 url 以进行身份验证
- json - jq中的向量数学算术运算
- javascript - 如何获取 html 表 React js 的更改文本
- node.js - Amazon DynamoDB :- 无效的 UpdateExpression:表达式大小已超过 dynamodb 允许的最大大小
- python - 在 python 中使用有效的 API 密钥提取位置信息时出现错误“SSLError”
- ruby - 如何在 Ruby 中使用 Net::LDAP 递归搜索 ldap 中的角色
- html - 如何将半个 div 与 CSS 网格对齐?
- elasticsearch - 用于 Ignite 的自定义 CacheStore 是否会自动进行后写?