Rad*_*dim 36 python generator pickle python-stackless
Python的泡菜(我说的是标准的Python 2.5/2.6/2.7)不能腌制锁,文件对象等.
它也不能pickle生成器和lambda表达式(或任何其他匿名代码),因为pickle实际上只存储名称引用.
在锁和依赖于操作系统的功能的情况下,原因为何你不能咸菜他们是明显的,是有道理的.
但为什么你不能发泡?
注:只是为了清楚起见, -我有兴趣的根本原因(或假设和进入该设计决策选择)为什么,而不是"因为它给你一个味酸错误".
我意识到这个问题有点广泛的目标,所以这里有一个经验法则,你是否回答:"如果这些假设被提出,或者允许的发电机的类型在某种程度上受到限制,那么酸洗发电机会再次工作吗?"
agf*_*agf 48
有很多关于这方面的信息.有关该问题的"官方消息",请阅读(已关闭)Python bugtracker问题.
由做出决定的人之一的核心推理在此博客上详细说明:
由于生成器本质上是一个加强函数,我们需要保存它的字节码,它不能保证在Python的版本之间向后兼容,并且它的框架保持生成器的状态,如局部变量,闭包和指令指针.而后者实现起来相当麻烦,因为它基本上需要使整个解释器可以选择.因此,对酸洗发生器的任何支持都需要对CPython核心进行大量更改.
现在,如果发生器的局部变量中出现了pickle不支持的对象(例如,文件句柄,套接字,数据库连接等),那么无论对发生器的任何pickle支持如何,都不能自动对该生成器进行pickle.实行.因此,在这种情况下,您仍然需要提供自定义
__getstate__和__setstate__方法.这个问题使得对发电机的任何酸洗支持都相当有限.
并提到了两个建议的解决方法:
无论如何,如果你需要这样的功能,那么请看看Stackless Python,它可以完成上述所有工作.由于Stackless的解释器是可选择的,因此您也可以免费获得进程迁移.这意味着你可以中断一个tasklet(Stackless的绿色线程的名称),pickle它,将pickle发送到另一台机器,unpickle它,恢复tasklet,并且你刚刚迁移了一个进程.这是一个很酷的功能!
但在我看来,这个问题的最佳解决方案是将生成器重写为简单的迭代器(即带有
__next__方法的迭代器).迭代器在空间方面很容易和有效,因为它们的状态是明确的.但是,您仍然需要明确地处理表示某个外部状态的对象; 你不能绕过这个.
zee*_*kay 23
你实际上可以,具体取决于实现.PyPy和Stackless Python都允许这个(在某种程度上):
Python 2.7.1 (dcae7aed462b, Aug 17 2011, 09:46:15)
[PyPy 1.6.0 with GCC 4.0.1] on darwin
Type "help", "copyright", "credits" or "license" for more information.
And now for something completely different: ``Not your usual analyses.''
>>>> import pickle
>>>> gen = (x for x in range(100))
>>>> next(gen)
0
>>>> pickled = pickle.dumps(gen)
>>>> next(pickle.loads(pickled))
1
Run Code Online (Sandbox Code Playgroud)
在CPython中,还可以创建一个迭代器对象来模拟可选择的生成器.
| 归档时间: |
|
| 查看次数: |
9975 次 |
| 最近记录: |