【发布时间】:2016-06-17 20:29:43
【问题描述】:
我有一段被pypy腌制的代码,但是,pypy添加了自己的操作码来扩展cpython操作码,cpython无法取消它(引发系统错误:未知操作码)。
由特殊操作码LOOKUP_METHOD & CALL_METHOD引起,参考the pypy doc
我想知道如何让 pypy 生成完全标准的 cpython 字节码,而不是自定义字节码。我查看了文档,找到了 PYTHONOPTIMIZE 环境变量,并将其设置为 0,但它不起作用。
附言我不能改变 unpickle 的一面,它必须是 cpython 2.7。
更新 1
正如评论所说,cpython 不能腌制或取消腌制代码对象,这是正确的。 我正在使用 cloudpickle 库来腌制和取消腌制功能对象, 在cloudpickle库中,可以pickle代码对象。
问题是pypy中co_code属性不同, 它包含仅在 pypy 中定义的特殊操作码。
更新 2
我采用@ecatmur 提供的方法,除了BUILD_LIST_FROM_ARG 外,它都可以正常工作。
下面是我的代码:
class my_func(object):
def __init__(self, resources):
self.file_resource = resources[0]
self.table_resource = resources[1]
self.valid_ids = [int(l) for l in self.file_resource]
self.valid_ids.extend([int(l[0]) for l in self.table_resource]) # issue line
在pypy端修改cloudpickle之后,我在cpython端unpikle:
c = pickle.loads('**the pypy pickled code**')
c([['0'], [['1']]])
但出现错误:
in __init__(self, resources)
453
454 self.valid_ids = [int(l) for l in self.file_resource]
--> 455 self.valid_ids.extend([int(l[0]) for l in self.table_resource])
456
457 def __call__(self, arg):
TypeError: 'int' object has no attribute '__getitem__'
我通过dis.dis查看了字节码,它是如此的连线,看起来很对。
如果我用 cpython 腌制,那么 unpickle 的一面就可以正常工作。
关于更新 2 的任何想法?
【问题讨论】:
-
CPython 无法腌制或取消腌制代码对象。也许您在 CPython 端使用 Stackless Python?或者您根本不是在谈论
pickle模块,而是在谈论编组或.pyc文件? -
对,@ArminRigo 我用cloudpickle库来pickle函数