Python 的 pickle 或者 shelve 库为什么不能 dump 一个 gevent 协程对象

2020-08-16 13:13:57 +08:00
 yangva

报错如下:

我进 pickle 库的源码看了,是用的 c 写的,所以代码被省略不可见了。 我网上搜了下,都没遇到我这个情况的(也可能我没找到),我试着把协程换成线程来 dump 也不行,线程报错是不能 dump 一个锁机制。

场景需求是这样的:

有个协程池,里面有多个协程对象在执行各自的任务(正在或者已完成),同时也有个 md5 映射表,表结构是{md5 值 1:gevent 协程对象 1,md5 值 2:gevent 协程对象 2,......}。

要能在这一堆协程对象里通过映射表找出正在执行的指定的某个协程对象,状态已完成的则不考虑,然后可以在它运行中途时能 kill 掉。

我本来打算用 pickle 库把这个 md5 表 dump 到数据库里,然后等需要结束某个协程对象时,再从数据库里 load 出来然后直接调用 kill 方法即可,结果就报上面的错。

希望各位大佬能指点小弟一二,我个人感觉关键点就在怎么从一堆携程对象识别出哪个是目标,md5 映射表是我自己加的,不是固定需求,如果有更好的方案那肯定更好,我洗耳恭听,小弟在此感谢各位大佬了。

2022 次点击
所在节点    Python
9 条回复
monsterxx03
2020-08-16 13:22:33 +08:00
greenlet 是不可以序列化的,不需要 md5,直接拿 greenlet.id 就行了,协程池在内存里维护 id 到 greenlet 的映射就行了,让协程池的程序暴露个接口,才能让外部来终止协程。
yangva
2020-08-16 13:54:59 +08:00
@monsterxx03 感谢大佬回复,我先试试
yangva
2020-08-16 14:05:26 +08:00
@monsterxx03 大佬,我刚试了下,有点尴尬的是,greenlet 没有 id 属性啊
monsterxx03
2020-08-16 14:28:45 +08:00
啊,记错了,greenlet 的唯一 id 应该是要和它的 parent 拼起来的,简单点直接用 id()取一个标识也行
cassidyhere
2020-08-16 14:35:13 +08:00
greenlet.getcurrent 。
你的需求和 flask 的实现好像,可以看看 werkzeug.local 的源码
yangva
2020-08-16 16:32:14 +08:00
@monsterxx03 好吧,谢谢
yangva
2020-08-16 16:32:28 +08:00
@cassidyhere 好的,谢谢,我去看看
abersheeran
2020-08-16 17:05:10 +08:00
gevent 我不熟。不过 pickle 序列化对象是需要有对目标对象的支持的,Python 内置对象不用说,基本都可以。但是其他对象必须实现两个方法才能序列化反序列化的。

https://stackoverflow.com/questions/1939058/simple-example-of-use-of-setstate-and-getstate
yangva
2020-08-16 17:23:21 +08:00
@abersheeran 好的,感谢大佬回复

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/698667

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX