不同服务器上的 Python 3.5 莳萝酸洗/解压:“KeyError: 'ClassType'" [英] Python 3.5 dill pickling/unpickling on different servers: "KeyError: 'ClassType'"

查看:71
本文介绍了不同服务器上的 Python 3.5 莳萝酸洗/解压:“KeyError: 'ClassType'"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在底部查看更新

--

这里有人问过类似的问题,但从未解决:pickling 和 unpickling 用户定义的类

我正在开发一个项目,该项目需要对用户定义的类进行酸洗,并将它们发送到远程服务器,在那里对它们进行解压和调用.我们使用 Dill 库来实现这一点,并取得了很多成功.

不幸的是,我遇到了一个问题,我很难调试.我创建并pickle一个类如下:

导入莳萝,base64导入时间,随机类周期源(对象):def __call__(self):为真:时间.睡眠(0.1)产量 random.uniform(20,100)period_src =periodicSource()a = base64.b64encode(dill.dumps(periodic_src)).decode("ascii")打印(一)

它创建了 dilled 类的 ascii 表示.

 <代码> gANjZGlsbC5kaWxsCl9jcmVhdGVfdHlwZQpxAChjZGlsbC5kaWxsCl9sb2FkX3R5cGUKcQFYCQAAAENsYXNzVHlwZXEChXEDUnEEWA4AAABwZXJpb2RpY1NvdXJjZXEFaAFYBgAAAG9iamVjdHEGhXEHUnEIhXEJfXEKKFgIAAAAX19jYWxsX19xC2NkaWxsLmRpbGwKX2NyZWF0ZV9mdW5jdGlvbgpxDChoAVgIAAAAQ29kZVR5cGVxDYVxDlJxDyhLAUsASwFLA0tjQyl4IgB0AABqAQBkAQCDAQABdAIAagMAZAIAZAMAgwIAVgFxAwBXZAAAU3EQKE5HP7mZmZmZmZpLFEtkdHERKFgEAAAAdGltZXESWAUAAABzbGVlcHETWAYAAAByYW5kb21xFFgHAAAAdW5pZm9ybXEVdHEWWAQAAABzZWxmcReFcRhYHwAAADxpcHl0aG9uLWlucHV0LTIwLTdhNGU5MDIwYWM2Yz5xGWgLSwdDBgABAwENAXEaKSl0cRtScRx9cR0oWAYAAAByYW5kb21xHmNkaWxsLmRpbGwKX2ltcG9ydF9tb2R1bGUKcR9oFIVxIFJxIVgEAAAAdGltZXEiaB9YBAAAAHRpbWVxI4VxJFJxJXVoC05OfXEmdHEnUnEoWAoAAABfX21vZHVsZV9fcSlYCAAAAF9fbWFpbl9fcSpYBwAAAF9fZG9jX19xK05YDQAAAF9fc2xvdG5hbWVzX19xLF1xLXV0cS5ScS8pgXEwLg ==

当我在另一台服务器上反序列化它时:

<预> <代码>一个= 'gANjZGlsbC5kaWxsCl9jcmVhdGVfdHlwZQpxAChjZGlsbC5kaWxsCl9sb2FkX3R5cGUKcQFYCQAAAENsYXNzVHlwZXEChXEDUnEEWA4AAABwZXJpb2RpY1NvdXJjZXEFaAFYBgAAAG9iamVjdHEGhXEHUnEIhXEJfXEKKFgIAAAAX19jYWxsX19xC2NkaWxsLmRpbGwKX2NyZWF0ZV9mdW5jdGlvbgpxDChoAVgIAAAAQ29kZVR5cGVxDYVxDlJxDyhLAUsASwFLA0tjQyl4IgB0AABqAQBkAQCDAQABdAIAagMAZAIAZAMAgwIAVgFxAwBXZAAAU3EQKE5HP7mZmZmZmZpLFEtkdHERKFgEAAAAdGltZXESWAUAAABzbGVlcHETWAYAAAByYW5kb21xFFgHAAAAdW5pZm9ybXEVdHEWWAQAAABzZWxmcReFcRhYHwAAADxpcHl0aG9uLWlucHV0LTIwLTdhNGU5MDIwYWM2Yz5xGWgLSwdDBgABAwENAXEaKSl0cRtScRx9cR0oWAYAAAByYW5kb21xHmNkaWxsLmRpbGwKX2ltcG9ydF9tb2R1bGUKcR9oFIVxIFJxIVgEAAAAdGltZXEiaB9YBAAAAHRpbWVxI4VxJFJxJXVoC05OfXEmdHEnUnEoWAoAAABfX21vZHVsZV9fcSlYCAAAAF9fbWFpbl9fcSpYBwAAAF9fZG9jX19xK05YDQAAAF9fc2xvdG5hbWVzX19xLF1xLXV0cS5ScS8pgXEwLg =='a = dill.loads(base64.b64decode(a.encode()))打印(一)

我收到以下错误:

/home/streamsadmin/anaconda3/bin/python/home/streamsadmin/git/streamsx.topology/test/python/topology/deleteme2.py回溯(最近一次调用最后一次):文件/home/streamsadmin/git/streamsx.topology/test/python/topology/deleteme2.py",第 40 行,在 <module> 中.a = dill.loads(base64.b64decode(a.encode()))文件/home/streamsadmin/anaconda3/lib/python3.5/site-packages/dill/dill.py",第277行,加载返回负载(文件)加载中的文件/home/streamsadmin/anaconda3/lib/python3.5/site-packages/dill/dill.py",第 266 行obj = pik.load()文件/home/streamsadmin/anaconda3/lib/python3.5/site-packages/dill/dill.py",第524行,_load_type返回_reverse_typemap[名称]KeyError: 'ClassType'

如果我在远程系统上使用不同版本的 Python,我会期待这一点,但它们是相同的:

服务器 1:

<预><代码>>>>导入系统>>>系统版本'3.5.2 |蟒蛇 4.1.1(64 位)|(默认,2016 年 7 月 2 日,17:53:06)\n[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)]'

服务器 2:

<预><代码>>>>导入系统>>>系统版本'3.5.2 |Anaconda 4.2.0(64 位)|(默认,2016 年 7 月 2 日,17:53:06)\n[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)]'

另外,Dill 的两个版本都是 0.2.6.有什么想法可以调试吗?

我认为这可能与我的环境有关.我使用的是 Python 3.5,但列出了内置类型:

<预><代码>>>>进口类型>>>目录(类型)['内置功能类型','内置方法类型','类类型','代码类型',...]

似乎 ClassType 在输出中应该 NOT 是这种情况,因为 ClassType 在 Python 3.5 中被删除了.这是非常奇怪的.

我在安装了 Python 2.7 和 Python 3.5 的系统上运行.2.7 安装会以某种方式污染 3.5 安装吗?

解决方案

罪魁祸首是 cloudpickle.默认情况下,在 Python 3.5 中, types.ClassType 未设置.

<预><代码>>>>进口类型>>>目录(类型)['BuiltinFunctionType', 'BuiltinMethodType', 'CodeType', ...]

当导入 cloudpickle 时,突然,types.ClassType 变成了定义.

<预><代码>>>>进口泡菜>>>目录(类型)['BuiltinFunctionType', 'BuiltinMethodType', 'ClassType', 'CodeType', ...]

服务器 A 使用 dill 来序列化对象,并导入 cloudpickle.因此,它在序列化期间包含对 ClassType 的引用.

服务器 B 不导入 cloudpickle,然后在反序列化过程中尝试查找对 ClassType 的引用并失败.引发错误:

回溯(最近一次调用最后一次):文件/home/streamsadmin/git/streamsx.topology/test/python/topology/deleteme2.py",第 40 行,在 <module> 中.a = dill.loads(base64.b64decode(a.encode()))文件/home/streamsadmin/anaconda3/lib/python3.5/site-packages/dill/dill.py",第277行,加载返回负载(文件)加载中的文件/home/streamsadmin/anaconda3/lib/python3.5/site-packages/dill/dill.py",第 266 行obj = pik.load()文件/home/streamsadmin/anaconda3/lib/python3.5/site-packages/dill/dill.py",第524行,_load_type返回_reverse_typemap[名称]KeyError: 'ClassType'

在我们的系统上,我们无法从环境中删除 cloudpickle,因此我们必须执行以下解决方法.

服务器 B 上,在我们导入 dill 之后和第一次调用 dill.loads 之前的某个时间,我们调用以下行代码:

dill._dill._reverse_typemap['ClassType'] = 类型

这适当地定义了 ClassType.并导致 dill 反序列化按预期工作.

See updates at the bottom

--

A similar question was asked here, but never resolved: pickling and unpickling user-defined class

I'm working on a project which necessitates pickling user defined classes, and sending them to a remote server where they are unpickled and called. We use the Dill library to accomplish this, and have had a lot of success.

Unfortunately, I've run into an issue I'm having a hard time debugging. I create and pickle a class as follows:

import dill, base64
import time, random

class periodicSource(object):
    def __call__(self):
        while True:
            time.sleep(0.1)
            yield random.uniform(20,100)

periodic_src = periodicSource()
a = base64.b64encode(dill.dumps(periodic_src)).decode("ascii")
print(a)

It creates an ascii representation of the dilled class.

gANjZGlsbC5kaWxsCl9jcmVhdGVfdHlwZQpxAChjZGlsbC5kaWxsCl9sb2FkX3R5cGUKcQFYCQAAAENsYXNzVHlwZXEChXEDUnEEWA4AAABwZXJpb2RpY1NvdXJjZXEFaAFYBgAAAG9iamVjdHEGhXEHUnEIhXEJfXEKKFgIAAAAX19jYWxsX19xC2NkaWxsLmRpbGwKX2NyZWF0ZV9mdW5jdGlvbgpxDChoAVgIAAAAQ29kZVR5cGVxDYVxDlJxDyhLAUsASwFLA0tjQyl4IgB0AABqAQBkAQCDAQABdAIAagMAZAIAZAMAgwIAVgFxAwBXZAAAU3EQKE5HP7mZmZmZmZpLFEtkdHERKFgEAAAAdGltZXESWAUAAABzbGVlcHETWAYAAAByYW5kb21xFFgHAAAAdW5pZm9ybXEVdHEWWAQAAABzZWxmcReFcRhYHwAAADxpcHl0aG9uLWlucHV0LTIwLTdhNGU5MDIwYWM2Yz5xGWgLSwdDBgABAwENAXEaKSl0cRtScRx9cR0oWAYAAAByYW5kb21xHmNkaWxsLmRpbGwKX2ltcG9ydF9tb2R1bGUKcR9oFIVxIFJxIVgEAAAAdGltZXEiaB9YBAAAAHRpbWVxI4VxJFJxJXVoC05OfXEmdHEnUnEoWAoAAABfX21vZHVsZV9fcSlYCAAAAF9fbWFpbl9fcSpYBwAAAF9fZG9jX19xK05YDQAAAF9fc2xvdG5hbWVzX19xLF1xLXV0cS5ScS8pgXEwLg==

When I go to deserialize it on the other server:

a = 'gANjZGlsbC5kaWxsCl9jcmVhdGVfdHlwZQpxAChjZGlsbC5kaWxsCl9sb2FkX3R5cGUKcQFYCQAAAENsYXNzVHlwZXEChXEDUnEEWA4AAABwZXJpb2RpY1NvdXJjZXEFaAFYBgAAAG9iamVjdHEGhXEHUnEIhXEJfXEKKFgIAAAAX19jYWxsX19xC2NkaWxsLmRpbGwKX2NyZWF0ZV9mdW5jdGlvbgpxDChoAVgIAAAAQ29kZVR5cGVxDYVxDlJxDyhLAUsASwFLA0tjQyl4IgB0AABqAQBkAQCDAQABdAIAagMAZAIAZAMAgwIAVgFxAwBXZAAAU3EQKE5HP7mZmZmZmZpLFEtkdHERKFgEAAAAdGltZXESWAUAAABzbGVlcHETWAYAAAByYW5kb21xFFgHAAAAdW5pZm9ybXEVdHEWWAQAAABzZWxmcReFcRhYHwAAADxpcHl0aG9uLWlucHV0LTIwLTdhNGU5MDIwYWM2Yz5xGWgLSwdDBgABAwENAXEaKSl0cRtScRx9cR0oWAYAAAByYW5kb21xHmNkaWxsLmRpbGwKX2ltcG9ydF9tb2R1bGUKcR9oFIVxIFJxIVgEAAAAdGltZXEiaB9YBAAAAHRpbWVxI4VxJFJxJXVoC05OfXEmdHEnUnEoWAoAAABfX21vZHVsZV9fcSlYCAAAAF9fbWFpbl9fcSpYBwAAAF9fZG9jX19xK05YDQAAAF9fc2xvdG5hbWVzX19xLF1xLXV0cS5ScS8pgXEwLg=='
a = dill.loads(base64.b64decode(a.encode()))
print(a)

I get the following error:

/home/streamsadmin/anaconda3/bin/python /home/streamsadmin/git/streamsx.topology/test/python/topology/deleteme2.py

Traceback (most recent call last):
 File "/home/streamsadmin/git/streamsx.topology/test/python/topology/deleteme2.py", line 40, in <module>
   a = dill.loads(base64.b64decode(a.encode()))
 File "/home/streamsadmin/anaconda3/lib/python3.5/site-packages/dill/dill.py", line 277, in loads
   return load(file)
 File "/home/streamsadmin/anaconda3/lib/python3.5/site-packages/dill/dill.py", line 266, in load
   obj = pik.load()
 File "/home/streamsadmin/anaconda3/lib/python3.5/site-packages/dill/dill.py", line 524, in _load_type
   return _reverse_typemap[name]
KeyError: 'ClassType'

I would expect this if I were using different version of Python on the remote system, but they're the same:

Server 1:

>>> import sys
>>> sys.version
'3.5.2 |Anaconda 4.1.1 (64-bit)| (default, Jul  2 2016, 17:53:06) \n[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)]'

Server 2:

>>> import sys
>>> sys.version
'3.5.2 |Anaconda 4.2.0 (64-bit)| (default, Jul  2 2016, 17:53:06) \n[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)]'

Additionally, both versions of Dill are 0.2.6. Any ideas how I could debug this?

EDIT: I've think it might be something with my environment. I'm using Python 3.5, but list the builtin types:

>>> import types
>>> dir(types)
  ['BuiltinFunctionType',
   'BuiltinMethodType',
   'ClassType',
   'CodeType',
   ...
  ]

It seems ClassType is in the output which should NOT be the case since ClassType was removed in Python 3.5. This is exceedingly strange.

I'm running on a system that has both Python 2.7 and Python 3.5 installed. Could the 2.7 installation somehow be polluting the 3.5 installation?

解决方案

The culprit is cloudpickle. By default in Python 3.5, types.ClassType is left unset.

>>> import types
>>> dir(types)
['BuiltinFunctionType', 'BuiltinMethodType', 'CodeType', ...]

When cloudpickle is imported, suddenly, types.ClassType becomes defined.

>>> import cloudpickle
>>> dir(types)
['BuiltinFunctionType', 'BuiltinMethodType', 'ClassType', 'CodeType', ...]

Server A uses dill to serialize objects, and also imports cloudpickle. Therefore it includes a reference to ClassType during serialization.

Server B does NOT import cloudpickle, and then tries to find a reference to ClassType during deserialization and fails. Raising the error:

Traceback (most recent call last):
 File "/home/streamsadmin/git/streamsx.topology/test/python/topology/deleteme2.py", line 40, in <module>
   a = dill.loads(base64.b64decode(a.encode()))
 File "/home/streamsadmin/anaconda3/lib/python3.5/site-packages/dill/dill.py", line 277, in loads
   return load(file)
 File "/home/streamsadmin/anaconda3/lib/python3.5/site-packages/dill/dill.py", line 266, in load
   obj = pik.load()
 File "/home/streamsadmin/anaconda3/lib/python3.5/site-packages/dill/dill.py", line 524, in _load_type
   return _reverse_typemap[name]
KeyError: 'ClassType'

On our system, we can't remove cloudpickle from our environment, so we had to do the following workaround.

On server B, right after we import dill and sometime before the first call to dill.loads, we invoke the following line of code:

dill._dill._reverse_typemap['ClassType'] = type

This defines ClassType appropriately. And causes dill deserialization to work as expected.

这篇关于不同服务器上的 Python 3.5 莳萝酸洗/解压:“KeyError: 'ClassType'"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆