- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我想序列化我的复杂对象。它看起来很简单,但每一步都会产生不同的问题。
最后,其他程序员也必须能够创建从我的父对象继承的复杂对象。对于 Python 2.7 和 Python3.x,这个对象应该是可 pickle 的。
我从一个简单的对象开始并使用了 pickle.dump
和 pickle.load
成功了。
然后我创建了多个复杂对象(相似但不相同),其中一些可以转储,而一些不能。
pickle 库knows哪些对象可以 pickle 或不 pickle 。理论上这意味着 pdb
可以自定义启用pickle调试。
我想要一个独立于对象内容的可靠序列化。于是又找了其他的序列化工具:
builtins.TypeError: <lib.scan.Content object at 0x7f37f1e5da50> is not JSON serializable
我已阅读 How to check if an object is pickleable没有给我答案。
我找到的最接近的是 How to find source of error in Python Pickle on massive object
我将其调整为:
import pickle
if _future_.isPython3():
class MyPickler(pickle._Pickler):
def save(self, obj):
try:
pickle._Pickler.save(self, obj)
except:
print ('pick(3.x) {0} of type {1}'.format(obj, type(obj)))
else:
class MyPickler (pickle.Pickler):
def save(self, obj):
try:
pickle.Pickler.save(self, obj)
except:
print('pick(2.x)', obj, 'of type', type(obj))
我使用以下代码调用此代码:
def save(obj, file):
if platform.python_implementation() == 'CPython':
myPickler = MyPickler(file)
myPickler.save(obj)
我希望在引发异常之前执行保存。 obj
的内容被打印出来,所以我可以准确地看到错误发生的位置。但结果是:
pick(3.x) <class 'module'> of type <class 'type'>
pick(3.x) <class 'module'> of type <class 'type'>
pick(3.x) <class 'Struct'> of type <class 'type'>
pick(3.x) <class 'site.setquit.<locals>.Quitter'> of type <class 'type'>
pick(3.x) <class 'site.setquit.<locals>.Quitter'> of type <class 'type'>
pick(3.x) <class 'module'> of type <class 'type'>
pick(3.x) <class 'sys.int_info'> of type <class 'type'>
...
这只是结果的一小部分。我不明白这一点。它不能帮助我 pickle 哪个细节是错误的。以及如何解决这个问题。
我见过:http://docs.python.org/3/library/pickle.html#what-can-be-pickled-and-unpickled但是如果我无法检测到我的代码中的哪一行不能被 pickle ,这对我没有多大帮助。
我的复杂对象中的代码按预期工作,最后运行生成的代码为:
sys.modules['unum']
但是在 pickle 时,“模块”似乎没有按预期读取。
一些背景来澄清我的意思。我曾经有过有效的程序,但突然不工作了。它可能是更新或其他更改资源。为他人工作而不为我和相反的程序。
这是一个普遍的问题,所以我想开发一个程序来检查所有类型的资源。各种资源的数量是巨大的。所以我有一个具有所有一般行为的父对象类。以及针对特定资源的尽可能小的细节类。
这是在我的子资源类中完成的。
这些资源必须使用不同的版本进行检查 f.e. Python 2.7 或 Python 3.3如果您使用 Python 2.7.5 运行,则如果需要 Python 2.7 及更高版本,则该资源有效。所以支票必须比相等的值多一点。这在自定义配置文件中指定为单个语句。每个程序都有一个特定的配置文件,必须尽可能小才能使用。使用配置文件中的一条语句检查一个资源。
通用类约占代码的 98%。具体的资源和配置只占代码的 2% 左右。因此很容易添加新资源进行检查,以及为新程序添加新配置文件。
这个子资源:
class R_Sys(r_base.R_Base):
'''
doc : http://docs.python.org/3/library/sys.html#module-sys
sys.modules returns only a list of imported module
statement :
sys.modules['psutil'] # may return false (installed but not imported
but the statements :
import psutil
sys.modules['psutil'] # will return true, now psutil is imported
'''
allowed_names = ('modules', 'path', 'builtin_module_names', 'stdin')
allowed_keys_in_dict_config = ('name',)
allowed_operators = ("R_NONE", "=", 'installed') # installed only for modules
class_group = 'Sys'
module_used = sys
def __init__(self, check_type, group, name):
super(R_Sys, self).__init__(check_type, group, name)
由该配置语句调用:
sc.analyse(r.R_Sys, c.ct('DETECT'), dict(name='path'))
可以成功 pickle 。但是使用配置语句:
sc.analyse(r.R_Sys, c.ct('DETECT'),
dict(name='modules', tuplename='unum') )
失败了。
这意味着在我看来 98% 的主代码应该是可以的,否则第一条语句也会失败。
子类中有类属性。这些是正常运行所必需的。再次在第一次调用转储执行良好。我还没有加载。
最佳答案
dill
有一些很好的 pickle 诊断工具,其中最好的是 pickle 跟踪(类似于你已经实现的)。
让我们构建一个复杂的对象,然后探索:
>>> import dill
>>> class Foo(object):
... @classmethod
... def bar(self, x):
... return self.z + x
... def baz(self, z):
... self.z = z
... z = 1
... zap = lambda self, x: x + self.bar(x)
...
>>> f = Foo()
>>> f.zap(3)
7
>>> f.baz(7)
>>> f.z
7
开启“pickle 痕迹”:
>>> dill.detect.trace(True)
>>> _f = dill.dumps(f)
T2: <class '__main__.Foo'>
F2: <function _create_type at 0x10f94a668>
T1: <type 'type'>
F2: <function _load_type at 0x10f94a5f0>
T1: <type 'object'>
D2: <dict object at 0x10f96bb40>
Cm: <classmethod object at 0x10f9ad408>
T4: <type 'classmethod'>
F1: <function bar at 0x10f9aa9b0>
F2: <function _create_function at 0x10f94a6e0>
Co: <code object bar at 0x10f9a9130, file "<stdin>", line 2>
F2: <function _unmarshal at 0x10f94a578>
D1: <dict object at 0x10e8d6168>
D2: <dict object at 0x10f96b5c8>
F1: <function baz at 0x10f9aaa28>
Co: <code object baz at 0x10f9a9ab0, file "<stdin>", line 5>
D1: <dict object at 0x10e8d6168>
D2: <dict object at 0x10f969d70>
F1: <function <lambda> at 0x10f9aaaa0>
Co: <code object <lambda> at 0x10f9a9c30, file "<stdin>", line 8>
D1: <dict object at 0x10e8d6168>
D2: <dict object at 0x10f97d050>
D2: <dict object at 0x10e97b4b0>
>>> f_ = dill.loads(_f)
>>> f_.z
7
好的,dill
可以 pickle 这个对象……所以让我们让它变得更难。我们首先关闭跟踪。
>>> dill.detect.trace(False)
>>>
>>> f.y = xrange(5)
>>> f.w = iter([1,2,3])
>>>
>>> dill.pickles(f)
False
好的,现在 dill
失败了。那么导致失败的原因是什么?如果我们深入我们的对象 f
,我们可以查看所有无法 pickle 的对象。
>>> dill.detect.badtypes(f)
<class '__main__.Foo'>
>>> dill.detect.badtypes(f, depth=1)
{'__hash__': <type 'method-wrapper'>, '__setattr__': <type 'method-wrapper'>, '__reduce_ex__': <type 'builtin_function_or_method'>, 'baz': <type 'instancemethod'>, '__reduce__': <type 'builtin_function_or_method'>, '__str__': <type 'method-wrapper'>, '__format__': <type 'builtin_function_or_method'>, '__getattribute__': <type 'method-wrapper'>, 'zap': <type 'instancemethod'>, '__delattr__': <type 'method-wrapper'>, '__repr__': <type 'method-wrapper'>, 'w': <type 'listiterator'>, '__dict__': <type 'dict'>, '__sizeof__': <type 'builtin_function_or_method'>, '__init__': <type 'method-wrapper'>}
>>> dill.detect.badobjects(f, depth=1)
{'__hash__': <method-wrapper '__hash__' of Foo object at 0x10f9b0050>, '__setattr__': <method-wrapper '__setattr__' of Foo object at 0x10f9b0050>, '__reduce_ex__': <built-in method __reduce_ex__ of Foo object at 0x10f9b0050>, 'baz': <bound method Foo.baz of <__main__.Foo object at 0x10f9b0050>>, '__reduce__': <built-in method __reduce__ of Foo object at 0x10f9b0050>, '__str__': <method-wrapper '__str__' of Foo object at 0x10f9b0050>, '__format__': <built-in method __format__ of Foo object at 0x10f9b0050>, '__getattribute__': <method-wrapper '__getattribute__' of Foo object at 0x10f9b0050>, 'zap': <bound method Foo.<lambda> of <__main__.Foo object at 0x10f9b0050>>, '__delattr__': <method-wrapper '__delattr__' of Foo object at 0x10f9b0050>, '__repr__': <method-wrapper '__repr__' of Foo object at 0x10f9b0050>, 'w': <listiterator object at 0x10f9b0550>, '__dict__': {'y': xrange(5), 'z': 7, 'w': <listiterator object at 0x10f9b0550>}, '__sizeof__': <built-in method __sizeof__ of Foo object at 0x10f9b0050>, '__init__': <method-wrapper '__init__' of Foo object at 0x10f9b0050>}
嗯。好多啊。当然,并非所有这些对象都必须序列化才能让我们的对象序列化……但至少有一个导致失败。
很自然的事情就是看看我们遇到的失败......那么,会抛出什么错误呢?也许这会给出提示。
>>> dill.detect.errors(f)
PicklingError("Can't pickle <type 'listiterator'>: it's not found as __builtin__.listiterator",)
啊哈,listiterator
是个坏对象。让我们通过重新打开“跟踪”来深入挖掘。
>>> dill.detect.trace(True)
>>> dill.pickles(f)
T2: <class '__main__.Foo'>
F2: <function _create_type at 0x10f94a668>
T1: <type 'type'>
F2: <function _load_type at 0x10f94a5f0>
T1: <type 'object'>
D2: <dict object at 0x10f9826e0>
Cm: <classmethod object at 0x10f9ad408>
T4: <type 'classmethod'>
F1: <function bar at 0x10f9aa9b0>
F2: <function _create_function at 0x10f94a6e0>
Co: <code object bar at 0x10f9a9130, file "<stdin>", line 2>
F2: <function _unmarshal at 0x10f94a578>
D1: <dict object at 0x10e8d6168>
D2: <dict object at 0x10f96b5c8>
F1: <function baz at 0x10f9aaa28>
Co: <code object baz at 0x10f9a9ab0, file "<stdin>", line 5>
D1: <dict object at 0x10e8d6168>
D2: <dict object at 0x10f969d70>
F1: <function <lambda> at 0x10f9aaaa0>
Co: <code object <lambda> at 0x10f9a9c30, file "<stdin>", line 8>
D1: <dict object at 0x10e8d6168>
D2: <dict object at 0x10f97d050>
D2: <dict object at 0x10e97b4b0>
Si: xrange(5)
F2: <function _eval_repr at 0x10f94acf8>
T4: <type 'listiterator'>
False
确实,它停在 listiterator
处。但是,请注意(就在上面) xrange
确实 pickle 。所以,让我们用 xrange
iter
>>> f.w = xrange(1,4)
>>> dill.detect.trace(False)
>>> dill.pickles(f)
True
>>>
我们的对象现在再次 pickle 。
dill
内置了许多其他 pickle 检测工具,包括跟踪哪个对象指向哪个对象的方法(用于调试递归 pickle 失败)。
我相信 cloudpickle
也有一些与 dill
类似的工具用于 pickle 调试……但在这两种情况下的主要工具都与您构建的类似。
关于python - 如何检查复杂对象的哪些细节不能被 pickle ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22233478/
前言 本文主要介绍了关于MySQL主键为0与主键自排约束的关系,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。 开始不设置主键表的设计如下: 如果id的位置有好几个0
我已经阅读了一些关于将消息从一个线程冒泡到所有其他线程以正常退出的正确方法的来源(每个线程都执行它自己的退出例程)。其中,我喜欢全局原子 bool 值的想法,它可以从任何线程进行标记,所有其他线程检查
本文深入探讨Go语言中的流程控制语法,包括基本的 if-else 条件分支、 for 循环、 switch-case 多条件分支,以及与特定数据类型相关的流程控制,如 for-r
我是 MVC 和 XCode 的新手,在将我对 MVC 的概念理解转化为设计和实现具体类时遇到了困难。我希望就如何构建 Controller 和 View 以获得预期的 UI 获得一些建议。这是针对
如果我尝试在 View 中打开 DeatilFragement,我的应用程序崩溃并收到以下错误: Caused by: java.lang.IllegalStateException: Require
我正在尝试构建我的 iOS 应用程序的界面。一遍又一遍地开始新项目我仍然遇到细节 View 控件的问题(见图)。 在这里我得到了截图: 详细 View 显示当用户触摸 UITableView 行时。您
我在与我正在处理的项目的类(class)中遇到问题。该类是一个接受标签和值的 GUI 组件。这里的想法是,用户可以指定一个标签,然后从任何地方链接一个值(更具体地说,该值的 ToString 方法),
嗯.. 我在我的应用程序中设置了表格 View - 详细 View 。 主视图使用常规代码将数据传递给详细 View - (void)tableView:(UITableView *)tableVie
我有 celery 任务,队列中有 100 个输入数据,需要使用 5 个 worker 来执行。 如何获取哪个工作人员正在执行哪个输入? 每个 worker 执行了多少输入及其状态? 如果任何任务失败
我有一个 .net github 项目,它基本上是一个 Web API 的包装器。在测试项目中,我使用 API key 调用 API。我需要将此 key 保密,如何在 Visual Studio 项目
我遇到一个问题,从 Ag-Grid 导出网格只会导出主网格的详细信息,而不会导出子网格。这是一个显示问题的 plunkr: https://next.plnkr.co/edit/jVcvWDJ1NKP
我在详细 View 中有一个不会消失的额外空间。该 View 来自 NavigationLink,但我已经尝试过使用或不使用 NavigationView。我试图包装它用 NavigationView
几天来,我一直在关注猫效应和 IO。我觉得我对这种效果有一些误解,或者只是我错过了它的重点。 首先——如果IO可以替代Scala的Future,我们如何创建异步IO任务?使用 IO.shift ?使用
如何将标高添加到主视图/详细 View 的详细信息 Pane 中,以在其下方提供阴影,同时定位为部分覆盖工具栏(如下面的底部图片)?我尝试使用 android:elevation="4dp" 但这对我
我试图在我的 UISplitViewController 的细节 View 上设置一个阴影,我希望在 iOS 6 中的主 View 上可见。 在我的细节 View Controller 中: sel
我正在阅读 std::basic_string::reserve(size_type res_arg=0) 上的标准.它是这样说的: void reserve(size_type res_arg=0)
Boost 文档说 Starting with Boost release 1.53, shared_ptr can be used to hold a pointer to a dynamicall
我用 OpenGL 编写了一个简单的 24 位位图加载器。我打开一个位图文件并读取它的像素,然后从中创建一个 RGB 像素数据数组,然后将其传递给 glDrawPixels()。 问题:我需要使图像的
for x in ...循环 就是把每个元素代入变量x,然后执行缩进块的语句。 range()函数,可以生成一个整数序列,再通过list()函数可以转换为list。 比如我们想计算1-10的整数
场景 我有一个 DevExpress XtraGrid。 显示的数据采用主/详细信息格式,点击行开头的“+”可展开该主行的详细信息。 我通过将网格数据源绑定(bind)到包含自己的字典属性(以保存详细
我是一名优秀的程序员,十分优秀!