Python 确定对象为什么可以';不要腌

Python 确定对象为什么可以';不要腌,python,pickle,Python,Pickle,我正在从类型为object的api接收一个对象t。我无法对其进行酸洗,出现错误: File "p.py", line 55, in <module> pickle.dump(t, open('data.pkl', 'wb')) File "/usr/lib/python2.6/pickle.py", line 1362, in dump Pickler(file, protocol).dump(obj) File "/usr/lib/python2.6/p

我正在从类型为
object
的api接收一个对象
t
。我无法对其进行酸洗,出现错误:

  File "p.py", line 55, in <module>
    pickle.dump(t, open('data.pkl', 'wb'))
  File "/usr/lib/python2.6/pickle.py", line 1362, in dump
    Pickler(file, protocol).dump(obj)
  File "/usr/lib/python2.6/pickle.py", line 224, in dump
    self.save(obj)
  File "/usr/lib/python2.6/pickle.py", line 313, in save
    (t.__name__, obj))
pickle.PicklingError: Can't pickle 'Object' object: <Object object at 0xb77b11a0>
我只得到字符串对象:

<type 'str'>
<type 'str'>
<type 'str'>
...
<type 'str'>
<type 'str'>
<type 'str'>

...
如何打印我的
对象的内容
对象才能理解为什么不能对其进行酸洗

对象也可能包含指向QT对象的C指针,在这种情况下,对我来说,pickle对象是没有意义的。但我想再次看到物体的内部结构,以建立这一点

之后,您可能需要阅读并检查API的
对象


关于“对象的内部结构”,实例属性通常存储在
\uuuuu dict\uuuu
属性中(由于类属性没有被pickle,所以您只关心实例属性),但是请注意,您还必须递归地检查每个属性的
\uuu dict\uuu

我会使用
dill
,它有一些工具来调查对象内部是什么导致目标对象不可拾取。请参阅此答案了解示例:,此问答了解实际使用的检测工具示例:

dill
还具有跟踪指向对象的指针、引用和引用的功能,因此您可以构建对象相互引用方式的层次结构。见:


另外,还有:cloudpickle.py和debugpickle.py,它们大部分不再开发。我是
dill
的作者,希望能很快将
dill

中缺少的任何功能合并到这些代码中。我尝试了dill,但没有解释我的问题。相反,我使用了中的以下代码,它碰巧在我的
\uuu getattribute\uuu
覆盖中显示了一个bug:

def debug_pickle(instance):
  """
  :return: Which attribute from this object can't be pickled?
  """
  attribute = None

  for k, v in instance.__dict__.iteritems():
      try:
          cPickle.dumps(v)
      except:
          attribute = k
          break

  return attribute

编辑:这是我的代码的复制,使用pickle和cPickle:

class myDict(dict):

    def __getattribute__(self, item):
        # Try to get attribute from internal dict
        item = item.replace("_", "$")

        if item in self:
            return self[item]

        # Try super, which may leads to an AttribueError
        return super(myDict, self).__getattribute__(item)

myd = myDict()

try: 
    with open('test.pickle', 'wb') as myf:
        cPickle.dump(myd, myf, protocol=-1)
except:
    print traceback.format_exc()


try:
    with open('test.pickle', 'wb') as myf:
        pickle.dump(myd, myf, protocol=-1)
except:
    print traceback.format_exc()
输出:

Traceback (most recent call last):
File "/Users/myuser/Documents/workspace/AcceptanceTesting/ingest.py", line 35, in <module>
  cPickle.dump(myd, myf, protocol=-1)
UnpickleableError: Cannot pickle <class '__main__.myDict'> objects

Traceback (most recent call last):
File "/Users/myuser/Documents/workspace/AcceptanceTesting/ingest.py", line 42, in <module>
  pickle.dump(myd, myf, protocol=-1)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1370, in dump
  Pickler(file, protocol).dump(obj)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 224, in dump
  self.save(obj)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 313, in save
  (t.__name__, obj))
PicklingError: Can't pickle 'myDict' object: {}
回溯(最近一次呼叫最后一次):
文件“/Users/myuser/Documents/workspace/AcceptanceTesting/inset.py”,第35行,在
cPickle.dump(myd,myf,protocol=-1)
UnpicklableError:无法pickle对象
回溯(最近一次呼叫最后一次):
文件“/Users/myuser/Documents/workspace/AcceptanceTesting/inset.py”,第42行,在
pickle.dump(myd,myf,protocol=-1)
文件“/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py”,第1370行,在转储文件中
Pickler(文件,协议).dump(obj)
文件“/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py”,转储文件第224行
自我保存(obj)
文件“/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py”,保存中第313行
(t.(姓名)(obj))
PicklingError:无法pickle'myDict'对象:{}
您将看到,原因是属性名称被
\uuuu getattribute\uuu

在Python3中,这里是的扩展名

它:

  • 是递归的,用于处理问题可能涉及多个层次的复杂对象

    输出格式为
    .x[i].y.z…
    ,以允许您查看调用了哪些成员来解决问题。使用
    dict
    它只打印
    [key/val type=…]
    ,因为键或值都可能是问题所在,这使得在
    dict
    中引用特定键或值变得更加困难(但并非不可能)

  • 说明了更多的类型,特别是
    列表
    元组
    dict
    ,这些类型需要单独处理,因为它们没有
    \uuu dict\uuu
    属性

  • 返回所有问题,而不仅仅是第一个问题


这似乎是通过调查
对象本身而不是实例来调试的。
dir()
返回字符串变量名列表,而不是变量本身的值。你能澄清一下你的意思吗
dill
没有帮助,但上面的代码有帮助?上述代码是
dill.detect
中存在的较弱版本的代码。具体来说,
dill.detect.badobjects
dill.detect.badtypes
dill
还有我的答案中显示的其他工具。如果这里缺少什么东西,我想知道。嗨@MikeMcKerns。迪尔看起来很棒,我只是不认为你能为我的愚蠢编写代码:)我用我的错误代码的复制品更新了我的问题。啊……好吧,你真的遇到了麻烦<代码>莳萝
在这种情况下没有发现问题,我同意。但是,您还会注意到,
debug\u pickle
实际上并没有返回bad属性……它只是碰巧没有捕获导致pickle失败的错误。有用,但似乎是无意的。我会把这个案子记下来作为迪尔的罚单。谢谢。有趣的是,我和迪尔都有这个:-(@iirekm:你能澄清一下你所说的“这个”是什么意思吗?)?
def debug_pickle(instance):
  """
  :return: Which attribute from this object can't be pickled?
  """
  attribute = None

  for k, v in instance.__dict__.iteritems():
      try:
          cPickle.dumps(v)
      except:
          attribute = k
          break

  return attribute
class myDict(dict):

    def __getattribute__(self, item):
        # Try to get attribute from internal dict
        item = item.replace("_", "$")

        if item in self:
            return self[item]

        # Try super, which may leads to an AttribueError
        return super(myDict, self).__getattribute__(item)

myd = myDict()

try: 
    with open('test.pickle', 'wb') as myf:
        cPickle.dump(myd, myf, protocol=-1)
except:
    print traceback.format_exc()


try:
    with open('test.pickle', 'wb') as myf:
        pickle.dump(myd, myf, protocol=-1)
except:
    print traceback.format_exc()
Traceback (most recent call last):
File "/Users/myuser/Documents/workspace/AcceptanceTesting/ingest.py", line 35, in <module>
  cPickle.dump(myd, myf, protocol=-1)
UnpickleableError: Cannot pickle <class '__main__.myDict'> objects

Traceback (most recent call last):
File "/Users/myuser/Documents/workspace/AcceptanceTesting/ingest.py", line 42, in <module>
  pickle.dump(myd, myf, protocol=-1)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1370, in dump
  Pickler(file, protocol).dump(obj)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 224, in dump
  self.save(obj)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 313, in save
  (t.__name__, obj))
PicklingError: Can't pickle 'myDict' object: {}
def get_unpicklable(instance, exception=None, string='', first_only=True):
    """
    Recursively go through all attributes of instance and return a list of whatever
    can't be pickled.

    Set first_only to only print the first problematic element in a list, tuple or
    dict (otherwise there could be lots of duplication).
    """
    problems = []
    if isinstance(instance, tuple) or isinstance(instance, list):
        for k, v in enumerate(instance):
            try:
                pickle.dumps(v)
            except BaseException as e:
                problems.extend(get_unpicklable(v, e, string + f'[{k}]'))
                if first_only:
                    break
    elif isinstance(instance, dict):
        for k in instance:
            try:
                pickle.dumps(k)
            except BaseException as e:
                problems.extend(get_unpicklable(
                    k, e, string + f'[key type={type(k).__name__}]'
                ))
                if first_only:
                    break
        for v in instance.values():
            try:
                pickle.dumps(v)
            except BaseException as e:
                problems.extend(get_unpicklable(
                    v, e, string + f'[val type={type(v).__name__}]'
                ))
                if first_only:
                    break
    else:
        for k, v in instance.__dict__.items():
            try:
                pickle.dumps(v)
            except BaseException as e:
                problems.extend(get_unpicklable(v, e, string + '.' + k))

    # if we get here, it means pickling instance caused an exception (string is not
    # empty), yet no member was a problem (problems is empty), thus instance itself
    # is the problem.
    if string != '' and not problems:
        problems.append(
            string + f" (Type '{type(instance).__name__}' caused: {exception})"
        )

    return problems