Estoy tratando de pepinillo un namedtuple:

from collections import namedtuple
import cPickle

class Foo:

    Bar = namedtuple('Bar', ['x', 'y'])

    def baz(self):
        s = set()
        s.add(Foo.Bar(x=2, y=3))
        print cPickle.dumps(s)

if __name__ == '__main__':
    f = Foo()
    f.baz()

Esto produce la siguiente salida:

Traceback (most recent call last):
  File "scratch.py", line 15, in <module>
    f.baz()
  File "scratch.py", line 11, in baz
    print cPickle.dumps(s)
cPickle.PicklingError: Can't pickle <class '__main__.Bar'>: attribute lookup __main__.Bar failed

¿Qué estoy haciendo mal? El problema es que Bar es un miembro de Foo? (Moviendo la definición de Bar para el nivel superior se soluciona el problema, aunque todavía estoy curioso por qué sucede esto.)

  • El uso de python3 y pepinillos protocolo 4 corrige este
  • Es @DaveButler ‘s respuesta correcta? ¿Alguien puede confirmar o desmentir?
InformationsquelleAutor Nick Heiner | 2011-01-13

3 Comentarios

  1. 28

    Sí, el hecho de que es un miembro de la clase es un problema:

    >>> class Foo():
    ...     Bar = namedtuple('Bar', ['x','y'])
    ...     def baz(self):
    ...         b = Foo.Bar(x=2, y=3)
    ...         print(type(b))
    ...
    >>> a = Foo()
    >>> a.baz()
    <class '__main__.Bar'>

    El problema es que cuando namedtuple() devuelve un objeto de tipo, no es consciente del hecho de que está siendo asignado a un miembro de la clase – y por lo tanto, se dice que el tipo de objeto que el nombre de su tipo debe ser __main__.Bar, aunque realmente debería ser __main__.Foo.Bar.

    • Así que… ¿hay alguna solución, o que simplemente prohibida?
    • namedtuple no juega bien con las clases. Usted puede ser capaz de escribir una costumbre __getstate__ para el objeto que iba a cuidar de él de forma manual.
    • docs.python.org/library/pickle.html#object.__getstate__
    • Sería un enlace anticipado que coge?
    • ¿Cómo podría yo usar getstate? No sé cómo implementar eso. En el momento estoy trabajando con una solución temporal que transfiere una lista de tuplas con nombre a un diccionario.
  2. 13

    De anidación de clases hace pickle fallar, ya que se basa en la trayectoria del objeto en el interior de su aplicación para reconstruir más tarde.

    La solución inmediata es no nido de clases, es decir, moverse Bar definición de fuera de Foo. Código de trabajo de todo el mismo.

    Pero la mejor cosa a hacer es no uso pickle a todos para almacenar datos. Utilizar algún otro formato de serialización, como json, o una base de datos, como sqlite3.

    Usted acaba de golpear a uno de los muchos inconvenientes de pepinillo, si cambia su código, mover cosas, o, a veces, hacer pequeños cambios estructurales, los datos se convierte en unloadable.

    Además de eso, pepinillo tiene otras desventajas: es lento, inseguro, python-sólo…

  3. 7

    El uso de eneldo en lugar de pepinillo aquí va a permitir que esto funcione

    • Por favor, dar el ejemplo de código
    • import dill; dill.dumps(x)
    • También esto no funciona para mí. Puedo obtener: no se Puede pickle <clase ‘RoadAttributesPartition’>: no se encuentra como principal.RoadAttributesPartition

Dejar respuesta

Please enter your comment!
Please enter your name here