He creado un objeto como este:

company1.name = 'banana' 
company1.value = 40

Me gustaría guardar este objeto. ¿Cómo puedo hacer eso?

  • Consulte ejemplo para la gente que viene aquí para ver un ejemplo sencillo de cómo utilizar vinagre.
  • ¿Por qué (aparentemente) prefiere que la respuesta a la aceptación de uno (de los vinculado pregunta)?
  • En el momento en que he enlazado, el aceptado respuesta no tiene protocol=pickle.HIGHEST_PROTOCOL. Mi respuesta también le ofrece alternativas para la vinagreta.
InformationsquelleAutor Peterstone | 2010-12-25

3 Comentarios

  1. 383

    Podría utilizar el pickle módulo en la biblioteca estándar.
    He aquí una aplicación elemental de que su ejemplo:

    import pickle
    
    class Company(object):
        def __init__(self, name, value):
            self.name = name
            self.value = value
    
    with open('company_data.pkl', 'wb') as output:
        company1 = Company('banana', 40)
        pickle.dump(company1, output, pickle.HIGHEST_PROTOCOL)
    
        company2 = Company('spam', 42)
        pickle.dump(company2, output, pickle.HIGHEST_PROTOCOL)
    
    del company1
    del company2
    
    with open('company_data.pkl', 'rb') as input:
        company1 = pickle.load(input)
        print(company1.name)  # -> banana
        print(company1.value)  # -> 40
    
        company2 = pickle.load(input)
        print(company2.name) # -> spam
        print(company2.value)  # -> 42

    También puede definir su propia utilidad sencilla como la siguiente, que abre un archivo y escribe un solo objeto: la

    def save_object(obj, filename):
        with open(filename, 'wb') as output:  # Overwrites any existing file.
            pickle.dump(obj, output, pickle.HIGHEST_PROTOCOL)
    
    # sample usage
    save_object(company1, 'company1.pkl')

    Actualización:

    Debido a que esto es una respuesta popular, me gustaría tocar en algunos ligeramente uso avanzado de los temas.

    cPickle (o _pickle) vs pickle

    Es casi siempre preferible a la realidad el uso de la cPickle módulo en lugar de pickle porque el primero está escrito en C y es mucho más rápido. Hay algunas sutiles diferencias entre ellos, pero en la mayoría de las situaciones son equivalentes y la versión en C proporcionará enormemente superior de rendimiento. El cambio a no podría ser más fácil, sólo cambia el import declaración a este:

    import cPickle as pickle

    En Python 3, cPickle fue rebautizado con el nombre _pickle, pero hacer esto no es necesario ya que el pickle módulo ahora lo hace automáticamente, ver Qué diferencia entre la salmuera y _pickle en python 3?.

    El resumen es que usted podría usar algo como lo siguiente para asegurarse de que el código se siempre utilizar la versión en C cuando está disponible tanto en Python 2 y 3:

    try:
        import cPickle as pickle
    except ModuleNotFoundError:
        import pickle

    De flujo de datos en los formatos (protocolos)

    pickle puede leer y escribir archivos en varios diferentes, Python específicos, formatos, protocolos como se describe en el documentación, «la versión de Protocolo 0» es ASCII y, por tanto, «legible». Versiones > 1 binario y el más alto disponible depende de qué versión de Python está siendo utilizado. El valor predeterminado depende también de la versión de Python. En Python 2 el defecto fue la versión de Protocolo de 0, pero en Python 3.7, es la versión de Protocolo de 3. En Python 3.x el módulo tenía un pickle.DEFAULT_PROTOCOL añadido a la misma, pero que no existe en Python 2.

    Afortunadamente, no es la abreviatura de la escritura pickle.HIGHEST_PROTOCOL en cada llamada (suponiendo que lo que usted desea, y usted suele hacer), sólo tiene que utilizar el número literal -1 — similar a que hace referencia el último elemento de una secuencia a través de un índice negativo.
    Así, en lugar de la escritura:

    pickle.dump(obj, output, pickle.HIGHEST_PROTOCOL)

    Sólo se pueden escribir:

    pickle.dump(obj, output, -1)

    De cualquier manera, usted solamente tendrá que especificar el protocolo de inmediato si usted creó un Pickler objeto para su uso en múltiples pickle operaciones:

    pickler = pickle.Pickler(output, -1)
    pickler.dump(obj1)
    pickler.dump(obj2)
       etc...

    Nota: Si estás en un entorno de ejecutar diferentes versiones de Python, entonces usted probablemente querrá utilizar explícitamente (es decir, codificar) un determinado número de protocolo que todos ellos se puede leer (y versiones posteriores, en general puede leer archivos producidos por los anteriores).

    Varios Objetos

    Mientras que un archivo pickle puede contener cualquier número de escabeche de objetos, como se muestra en los ejemplos anteriores, cuando hay un número desconocido de ellos, es a menudo más fácil almacenarlos todos en algún tipo de variable tamaño de un contenedor, como un list, tuple, o dict y escribirlos todos los archivos en una sola llamada:

    tech_companies = [
        Company('Apple', 114.18), Company('Google', 908.60), Company('Microsoft', 69.18)
    ]
    save_object(tech_companies, 'tech_companies.pkl')

    y restaurar la lista y todo lo que en él más tarde con:

    with open('tech_companies.pkl', 'rb') as input:
        tech_companies = pickle.load(input)

    La principal ventaja es que usted no necesita saber cuántas instancias de objetos se guardan en orden a cargar de nuevo más tarde (aunque hacerlo sin que la información es posible, se requiere de algunos ligeramente código especializado). Véanse las respuestas a la pregunta relacionada con la Guardar y cargar varios objetos en el archivo pickle? para más detalles sobre las diferentes maneras de hacer esto. Personalmente me como @Lutz Prechelt del respuesta la mejor. He aquí que se adapta a los ejemplos aquí:

    class Company:
        def __init__(self, name, value):
            self.name = name
            self.value = value
    
    def pickled_items(filename):
        """ Unpickle a file of pickled data. """
        with open(filename, "rb") as f:
            while True:
                try:
                    yield pickle.load(f)
                except EOFError:
                    break
    
    print('Companies in pickle file:')
    for company in pickled_items('company_data.pkl'):
        print('  name: {}, value: {}'.format(company.name, company.value))
    • Esto es raro para mí, porque me imaginaba que habría una forma más fácil guardar un objeto… Algo así como ‘saveobject(empresa1,c:\mypythonobjects)
    • Si sólo desea almacenar un objeto que sólo se necesitan alrededor de la mitad tanto el código como en mi ejemplo, escribió a propósito de la forma que yo hice para mostrar cómo más de un objeto puede ser guardado en (y después de leer de nuevo desde el mismo archivo.
    • hay una muy buena razón para la separación de responsabilidades. De esta manera no hay ninguna limitación sobre cómo los datos de la operación de decapado proceso está siendo utilizado. Usted puede almacenar en un disco, o también se puede enviar a través de una conexión de red.
    • Scheirich: ¿Podría por favor explicar qué quiere decir acerca de «la separación de responsabilidades» — no estoy exactamente seguro de lo que usted se refiere.
    • esto fue en respuesta a perstones comentario acerca de que uno debe tener sólo una función para guardar un objeto en el disco. Los encurtidos responsabilidad es solo a su vez un objeto de datos que puede ser manejado como un pedazo. Escribir cosas que archivo es el archivo de objetos de responsabilidad. Por mantener las cosas separadas permite una mayor reutilización por ejemplo, ser capaz de enviar el vinagre de datos a través de una conexión de red o almacenamiento en una base de datos, todas las responsabilidades por separado a partir de los datos reales<->objeto de conversión
    • Scheirich: Ah, ya veo…y estoy de acuerdo 😉 pero la duda Peterstone es ni capaz de apreciar las sutilezas del diseño de alto nivel de los distintos módulos de Python y de cómo encajan en esta etapa.
    • Eliminar company1 y company2. ¿Por qué no eliminar también Company y mostrar lo que pasa?
    • Principalmente porque, al hacerlo, tiene poco que ver con la pregunta en cuestión, ni tampoco es algo que la mayoría de la gente de leer el hilo son probable que se quiere hacer. Pero también porque tengo la fuerte sospecha de que la principal motivación para pedirle que no es nada más que un intento velado para dar a conocer el dill módulo escribió — que ciertamente suena como que podría ser útil en algunas situaciones.
    • no es un intento velado… cuando tienes un martillo, usted encuentra que usted vea que hay clavos por todas partes. De todos modos… es un punto válido para que me levante… y se ha preguntado varias veces sobre ESO.
    • Lo siento, no creo que esta pregunta es el tipo correcto de las uñas. Por lo que vale, creo que una manera eficaz de promover dill sería más claramente lo que puede hacer que pickle no puede en su página de descarga, en lugar de proponer su uso para resolver problemas no relacionados con el problema a mano en varios PARA que las entradas. Si hay un consenso en que se aborda adecuadamente las graves deficiencias de las personas son comúnmente encontrar al intentar utilizar pickle, quizás debería ser parte de la biblioteca estándar.
    • No estoy de acuerdo. Mire la cuestión. Es bastante fuerte suposición de suponer que el objeto de la OP está preguntando acerca de que es de una clase. Si no es una clase, entonces pickle fallan en la mayoría de los casos. Mi respuesta es más general, por lo que el tipo correcto de las uñas. Yo estaba recogiendo una costra un poco en los comentarios de tu respuesta, pero aún así en mi opinión un punto válido. Usted tiene todo el derecho a estar en desacuerdo. …y yo no estoy realmente tratando de promover dill, sólo estoy respondiendo a la pregunta con todas las herramientas que tengo en mi caja de herramientas.
    • ¿Qué es si puedo crear mis objetos en un bucle for (debido a las diferentes combinaciones de parámetros). El tiene que ser nombrado en una manera diferente de llegar más tarde de acceso a ella, no es. Y si sí, entonces ¿cómo podría yo crear diferentes nombres para mis objetos en un bucle for?
    • Se podrían crear diferentes nombres mediante la definición de un contador se inicializa antes de entrar en el for bucle y, a continuación, en su interior para generar cada nombre de archivo. es decir,filename = 'myname{}.pkl'.format(count), seguido por count += 1. Sin embargo, probablemente sería mejor poner todos los objetos en una lista y pickle.dump(), que salvará a todos ellos a la vez en un solo archivo y preservar el orden en que aparecen en la lista. Usted también puede poner en un diccionario y dump() que.
    • Promover la idea de usar el vinagre.HIGHEST_PROTOCOL. Pero ¿no es un poco riesgoso en el largo plazo? Si almacena su objeto en el formato de la versión x de Python 3.6 pero más adelante cambiar a una versión más reciente de Python donde la vinagreta.HIGHEST_PROTOCOL se refiere al formato de la versión x+1 entonces no podría ser capaz de cargar más de sus datos, a la derecha? Esta es la razón por la que pienso que sería mejor elegir conscientemente la actualidad de versión más alto. A continuación, puede actualizar Python y migrar el formato más tarde.
    • O es la versión que se utiliza para almacenar el objeto(s) parte de los datos para el proceso de lectura conoce la versión y siempre se puede cargar los datos con la versión correcta?
    • Sí, el protocolo utilizado se almacena en el archivo. Después versiones deben ser capaces de leer archivos producidos por una de las versiones anteriores. En un entorno donde una mezcla de versiones de Python están siendo utilizados, lo que dices tiene sentido. I «promovido» el uso de HIGHEST_PROTOCOL ya que generalmente se va a producir el más pequeño (y probablemente la más rápida) resultados.
    • Gracias por la respuesta, eso es muy bueno saber! Otros se preguntarán acerca de ese aspecto, así por lo que podría tocar que en su respuesta, si usted quiere.
    • Añade un poco de algo para el flujo de Datos formatos de la sección.

  2. 43

    Creo que es bastante fuerte presunción a suponer que el objeto es un class. ¿Y si no es un class? También existe la suposición de que el objeto no se ha definido en el intérprete. Lo que si fue definido en el intérprete? También, ¿qué pasa si los atributos se han añadido de forma dinámica? Cuando algunos de los objetos de python tienen atributos añadidos a su __dict__ después de la creación, pickle no respetar la adición de los atributos (es decir, se ‘olvida’ que se han añadido — porque pickle serializa por referencia a la definición del objeto).

    En todos estos casos, pickle y cPickle puede fallar terriblemente.

    Si usted está mirando para ahorrar un object (creados de forma arbitraria), donde usted tiene atributos (ya sea en la definición del objeto, o después)… la mejor opción es utilizar dill, que puede serializar casi nada en python.

    Empezamos con una clase de…

    Python 2.7.8 (default, Jul 13 2014, 02:29:54) 
    [GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import pickle
    >>> class Company:
    ...     pass
    ... 
    >>> company1 = Company()
    >>> company1.name = 'banana'
    >>> company1.value = 40
    >>> with open('company.pkl', 'wb') as f:
    ...     pickle.dump(company1, f, pickle.HIGHEST_PROTOCOL)
    ... 
    >>> 

    Ahora apagar y reiniciar…

    Python 2.7.8 (default, Jul 13 2014, 02:29:54) 
    [GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import pickle
    >>> with open('company.pkl', 'rb') as f:
    ...     company1 = pickle.load(f)
    ... 
    Traceback (most recent call last):
      File "<stdin>", line 2, in <module>
      File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1378, in load
        return Unpickler(file).load()
      File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 858, in load
    dispatch[key](self)
      File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1090, in load_global
        klass = self.find_class(module, name)
      File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1126, in find_class
        klass = getattr(mod, name)
    AttributeError: 'module' object has no attribute 'Company'
    >>> 

    Oops… pickle no puede manejar. Vamos a tratar de dill. Vamos a lanzar en otro tipo de objeto (un lambda) para la buena medida.

    Python 2.7.8 (default, Jul 13 2014, 02:29:54) 
    [GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import dill       
    >>> class Company:
    ...     pass
    ... 
    >>> company1 = Company()
    >>> company1.name = 'banana'
    >>> company1.value = 40
    >>> 
    >>> company2 = lambda x:x
    >>> company2.name = 'rhubarb'
    >>> company2.value = 42
    >>> 
    >>> with open('company_dill.pkl', 'wb') as f:
    ...     dill.dump(company1, f)
    ...     dill.dump(company2, f)
    ... 
    >>> 

    Y ahora lee el archivo.

    Python 2.7.8 (default, Jul 13 2014, 02:29:54) 
    [GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import dill
    >>> with open('company_dill.pkl', 'rb') as f:
    ...     company1 = dill.load(f)
    ...     company2 = dill.load(f)
    ... 
    >>> company1 
    <__main__.Company instance at 0x107909128>
    >>> company1.name
    'banana'
    >>> company1.value
    40
    >>> company2.name
    'rhubarb'
    >>> company2.value
    42
    >>>    

    Funciona. La razón pickle falla, y dill no, es que dill trata __main__ como un módulo (la mayor parte), y también puede pickle definiciones de clase en lugar de decapado por referencia (como pickle hace). La razón dill puede pickle un lambda es que se le da un nombre… entonces el decapado de la magia puede suceder.

    De hecho, hay una manera fácil de ahorrar todos estos objetos, especialmente si usted tiene un montón de objetos que hemos creado. Acaba de volcar toda python sesión y volver a ella más tarde.

    Python 2.7.8 (default, Jul 13 2014, 02:29:54) 
    [GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import dill
    >>> class Company:
    ...     pass
    ... 
    >>> company1 = Company()
    >>> company1.name = 'banana'
    >>> company1.value = 40
    >>> 
    >>> company2 = lambda x:x
    >>> company2.name = 'rhubarb'
    >>> company2.value = 42
    >>> 
    >>> dill.dump_session('dill.pkl')
    >>> 

    Ahora apague el ordenador, ir a disfrutar de un café o lo que sea, y volver más tarde…

    Python 2.7.8 (default, Jul 13 2014, 02:29:54) 
    [GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import dill
    >>> dill.load_session('dill.pkl')
    >>> company1.name
    'banana'
    >>> company1.value
    40
    >>> company2.name
    'rhubarb'
    >>> company2.value
    42
    >>> company2
    <function <lambda> at 0x1065f2938>

    El único gran inconveniente es que dill no es parte de la biblioteca estándar de python. Así que si usted no puede instalar un paquete de python en el servidor, entonces usted no puede utilizarlo.

    Sin embargo, si usted es capaz de instalar los paquetes de python en su sistema, usted puede obtener las últimas dill con git+https://github.com/uqfoundation/[email protected]#egg=dill. Y usted puede obtener la última versión liberada con pip install dill.

    • Me estoy poniendo un TypeError: __new__() takes at least 2 arguments (1 given) al intentar utilizar dill (que parece prometedor) con un objeto complejo que incluye un archivo de audio.
    • Usted está recibiendo un TypeError cuando usted hace qué, exactamente? Que suele ser un signo de un número incorrecto de argumentos al crear instancias de una instancia de la clase. Si esto no es parte del flujo de trabajo de la pregunta anterior, ¿podría publicar como otra pregunta, envíe a mí a través de correo electrónico, o agregarlo como un problema en el dill página de github?
    • Para cualquier persona siguiendo, aquí está el una pregunta relacionada con la @MikeLL publicado — a partir de la respuesta, al parecer no era un dill problema.
  3. 3

    Puede utilizar anycache para hacer el trabajo para usted. Considera todos los detalles:

    • Utiliza eneldo como backend,
      que se extiende a la de python pickle módulo para manejar lambda y todos los lindos
      características de python.
    • Almacena objetos diferentes para diferentes archivos y vuelve a cargar de forma adecuada.
    • Límites de tamaño de la caché de
    • Permite caché de compensación
    • Permite el intercambio de objetos entre varias pistas
    • Permite el respeto de los archivos de entrada que influyen en el resultado

    Suponiendo que se tiene una función myfunc que crea la instancia:

    from anycache import anycache
    
    class Company(object):
        def __init__(self, name, value):
            self.name = name
            self.value = value
    
    @anycache(cachedir='/path/to/your/cache')    
    def myfunc(name, value)
        return Company(name, value)

    Anycache llamadas myfunc en el primer tiempo y encurtidos el resultado de un
    archivo en cachedir el uso de un identificador único (dependiendo del nombre de la función y sus argumentos) como nombre de archivo.
    En cualquier período de ejecución, el vinagre objeto está cargado.
    Si el cachedir se conserva entre python se ejecuta, el vinagre objeto es tomado de la anterior ejecución de python.

    Para más detalles, véase el documentación

    • ¿Cómo se podía utilizar anycache guardar más de una instancia de, digamos, un class o contenedor, como un list (que no fue el resultado de una llamada a una función)?

Dejar respuesta

Please enter your comment!
Please enter your name here