serialización de datos de python (json / pickle / shelve)

Tabla de contenido

Uno, módulo json

1. Serialización y deserialización

2. Correspondencia de tipos de datos entre JSON y Python

3. Ejemplo: serialización / deserialización de tipos de datos personalizados

Dos, módulo de pepinillos

1. Comparación del módulo pickle y el módulo json

2. Formato de flujo de datos utilizado por el módulo pickle

3. Funciones relacionadas proporcionadas por el módulo pickle

4. Ejemplo: serialización / deserialización de tipos de datos integrados

5. Ejemplo: serialización / deserialización de tipos de datos personalizados

Módulo de tres estantes

Ejemplo: operación de tipo de datos incorporada

Ejemplo: operación de tipo de datos personalizado

Cinco, resumen

1. Contraste

2. Sugerencias

3. Apéndice


El proceso de convertir un objeto en un formato de datos que se puede transmitir a través de la red o almacenar en un disco local (como XML, JSON o una cadena de bytes en un formato específico) se llama serialización ; viceversa, se llama deserialización. .

Esta sección presentará varios módulos de Python integrados para la serialización de datos:

Nombre del módulo descripción API proporcionada
json Se utiliza para realizar la conversión entre tipos de datos de Python y cadenas generales (json) volcados () 、 volcado () 、 cargas () 、 carga ()
pepinillo Se utiliza para realizar la conversión entre tipos de datos de Python y formatos binarios específicos de Python volcados () 、 volcado () 、 cargas () 、 carga ()
dejar de lado Se utiliza especialmente para conservar datos del tipo de datos de Python en el disco. Shelve es un objeto similar a un dictado, que es muy conveniente de operar. abierto()

Uno, módulo json


1. Serialización y deserialización

Los procesos de serialización y deserialización del módulo JSON de Python se denominan codificación y decodificación respectivamente.

  • codificación:  convierte objetos Python en cadenas JSON
  • decodificación:  convierte la cadena JSON en un objeto python

El módulo json proporciona los siguientes dos métodos para la serialización y deserialización:

# 序列化:将Python对象转换成json字符串
dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)

# 反序列化:将json字符串转换成Python对象
loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

Además, el módulo json también proporciona dos métodos adicionales que nos permiten guardar directamente los datos json serializados en un archivo y leer directamente los datos json en el archivo para la deserialización:

# 序列化:将Python对象转换成json字符串并存储到文件中
dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)

# 反序列化:读取指定文件中的json字符串并转换成Python对象
load(fp, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

Parámetro sort_keys:  indica si ordenar las claves del dict durante la serialización (dict está desordenado por defecto)

El parámetro sangría:  indica el significado de la sangría, lo que puede hacer que el formato de almacenamiento de datos sea más elegante y más legible; si sangría es un entero o una cadena no negativa, los elementos de la matriz JSON y los miembros del objeto serán correspondientes Si sangría es 0 o un número negativo o una cadena vacía, solo se insertarán saltos de línea sin sangría.

Asegúrese de que el parámetro ascii:  cuando el valor de este parámetro es Verdadero (el valor predeterminado), todos los caracteres no ASCII en la salida (como el chino) se escaparán en una secuencia de '\ uXXXX', y el resultado estará completamente compuesto de Caracteres ASCII La instancia str. Si queremos obtener una salida legible por humanos, debemos establecer el valor del parámetro secure_ascii en False.

Nota:  De hecho, '\ uXXXX' es el valor de codificación de memoria correspondiente a los caracteres Unicode, el nombre de codificación de memoria es "unicode-escape", podemoscompletar la conversión mutua entre la cadena Unicode y la secuencia de codificación de memoria Unicodemedianteunicodestr.encode('unicode-escape')sumadecode('unicode-escape'), como se muestra a continuación :

Cabe señalar que: Si intenta utilizar el mismo fp para llamar repetidamente a la función dump () para serializar varios objetos (o para serializar el mismo objeto varias veces), se generará un archivo JSON no válido, lo que significa que para uno fp solamente Puede llamar a dump () una vez.

2. Correspondencia de tipos de datos entre JSON y Python

Python a JSON

Pitón JSON
dictar Objeto
lista, tupla formación
str cuerda
Enums derivados de int, float, int y float números
Cierto cierto
Falso falso
Ninguno nulo

JSON a Python

JSON Pitón
objeto dictar
formación lista
cuerda str
número (int) En t
número (real) flotador
cierto Cierto
falso Falso
nulo Ninguno

Descripción:

  • Las claves que no son cadenas en el dictado de Python se convertirán en cadenas en minúsculas cuando se conviertan en cadenas JSON;
  • Las tuplas en Python se convertirán en matrices durante la serialización, pero las matrices se convertirán en listas durante la deserialización;
  • De los dos puntos anteriores, cuando el objeto Python contiene datos de tupla o contiene dict, y hay una clave que no es una cadena en el dict, el resultado obtenido después de la deserialización es inconsistente con el objeto Python original;
  • Para los tipos de datos integrados de Python (como: str, unicode, int, float, bool, None, list, tuple, dict), el módulo json puede serializar / deserializar directamente; para objetos de clase personalizados, serializar y al deserializar, necesitamos definir un método para completar la conversión entre la definición de objeto y dict.

 

3. Ejemplo: serialización / deserialización de tipos de datos personalizados

Python es un lenguaje de programación orientado a objetos, podemos personalizar los tipos de datos que necesitamos; en el trabajo real, a menudo usamos las operaciones de serialización y deserialización de tipos de datos personalizados. Hay dos formas de lograr la serialización y deserialización de tipos de datos personalizados:

  • Realizado por función de conversión
  • Implementado heredando las clases JSONEncoder y JSONDecoder

Primero personalice un tipo de datos

class Student(object):
    def __init__(self, name, age, sno):
        self.name = name
        self.age = age
        self.sno = sno
    
    def __repr__(self):
        return 'Student [name: %s, age: %d, sno: %d]' % (self.name, self.age, self.sno)

Llamar al método dumps () directamente provocará un error TypeError:

>>> stu = Student('Tom', 19, 1)
>>> print(stu)
Student [name: Tom, age: 19, sno:   1]
>>>
>>> json.dumps(stu)
...
TypeError: Student [name: Tom, age: 19, sno:   1] is not JSON serializable

La información de excepción anterior señala: El objeto stu no se puede serializar en datos en formato JSON . Luego, implementamos la serialización JSON y la deserialización de este tipo de datos personalizados "escribiendo funciones de conversión" y "heredando las clases JSONEncoder y JSONDecoder" respectivamente.

Método 1: escribir una función de conversión

Entonces, ¿qué dos tipos de datos debería convertir esta función de conversión?  De la tabla correspondiente de tipos de datos JSON y Python enumerados anteriormente, el objeto en JSON corresponde al dict en Python. Por lo tanto, para serializar objetos de tipos de datos personalizados en Python, primero debe serializar este objeto. La conversión al módulo json puede directamente serializar el tipo de dictado. Se puede ver que esta función de conversión es para completar la conversión mutua entre objetos Python (no objetos JSON) y dict, y el proceso de conversión durante la serialización es "Objeto Python -> dict -> objeto JSON", secuencia inversa El proceso de transformación es "objeto JSON -> dict -> objeto Python". Por lo tanto, necesitamos escribir dos funciones de conversión para implementar el proceso de conversión durante la serialización y deserialización respectivamente.

def obj2dict(obj):
    d = {}
    d['__class__'] = obj.__class__.__name__
    d['__module__'] = obj.__module__
    d.update(obj.__dict__)
    return d

def dict2obj(d):
    if '__class__' in d:
        class_name = d.pop('__class__')
        module_name = d.pop('__module__')
        module = __import__(module_name)
        class_ = getattr(module, class_name)
        args = dict((key.encode('ascii'), value) for key, value in d.items())
        instance = class_(**args)
    else:
        instance = d
    return instance

Prueba de serialización:

>>> import json

>>> obj2dict(stu)
{'sno': 1, '__module__': '__main__', 'age': 19, '__class__': 'Student', 'name': 'Tom'}

>>> json.dumps(obj2dict(stu))
'{"sno": 1, "__module__": "__main__", "age": 19, "__class__": "Student", "name": "Tom"}'

>>> json.dumps(stu, default=obj2dict)
'{"sno": 1, "__module__": "__main__", "age": 19, "__class__": "Student", "name": "Tom"}'

json.dumps(stu, default=obj2dict) Equivalente a json.dumps(obj2dict(stu))

Prueba de deserialización:

>>> json.loads('{"sno": 1, "__module__": "__main__", "age": 19, "__class__": "Student", "name": "Tom"}')
{u'sno': 1, u'__module__': u'__main__', u'age': 19, u'name': u'Tom', u'__class__': u'Student'}

>>> dict2obj(json.loads('{"sno": 1, "__module__": "__main__", "age": 19, "__class__": "Student", "name": "Tom"}'))
Student [name: Tom, age: 19, sno: 1]

>>> json.loads('{"sno": 1, "__module__": "__main__", "age": 19, "__class__": "Student", "name": "Tom"}', object_hook=dict2obj)
Student [name: Tom, age: 19, sno: 1]

json.loads(JSON_STR, object_hook=dict2obj) Equivalente a dict2obj(json.loads(JSON_STR)) 

Método 2: heredar JSONEncoder y JSONDecoder para implementar subclases

import json

class MyJSONEncoder(json.JSONEncoder):
    def default(self, obj):
        d = {}
        d['__class__'] = obj.__class__.__name__
        d['__module__'] = obj.__module__
        d.update(obj.__dict__)
        return d

class MyJSONDecoder(json.JSONDecoder):
    def __init__(self):
        json.JSONDecoder.__init__(self, object_hook=self.dict2obj)
    
    def dict2obj(self, d):
        if '__class__' in d:
            class_name = d.pop('__class__')
            module_name = d.pop('__module__')
            module = __import__(module_name)
            class_ = getattr(module, class_name)
            args = dict((key.encode('ascii'), value) for key, value in d.items())
            instance = class_(**args)
        else:
            instance = d
        return instance

Prueba de serialización:

>>> stu = Student('Tom', 19, 1)

# 方式一:直接调用子类MyJSONEncoder的encode()方法进行序列化
>>> MyJSONEncoder().encode(stu)
'{"__class__": "Student", "__module__": "__main__", "name": "Tom", "age": 19, "sno": 1}'
>>> MyJSONEncoder(separators=(',', ':')).encode(stu)
'{"__class__":"Student","__module__":"__main__","name":"Tom","age":19,"sno":1}'

# 方式二:将子类MyJSONEncoder作为cls参数的值传递给json.dumps()函数
>>> json.dumps(stu, cls=MyJSONEncoder)
'{"__class__": "Student", "__module__": "__main__", "name": "Tom", "age": 19, "sno": 1}'
>>> json.dumps(stu, cls=MyJSONEncoder, separators=(',', ':'))
'{"__class__":"Student","__module__":"__main__","name":"Tom","age":19,"sno":1}'

Prueba de deserialización:

>>> MyJSONDecoder().decode('{"sno": 1, "__module__": "__main__", "age": 19, "__class__": "Student", "name": "Tom"}')
Student [name: Tom, age: 19, sno: 1]

Nota:  Después de la prueba, se encuentra queMyJSONDecoder().decode(JSON_STR) y json.loads(JSON_STR, object_hook=dict2obj) solo se puede ejecutar correctamentejson.loads(JSON_STR, cls=MyJSONDecoder) en Python 2.7, pero no se puede ejecutar correctamente en Python 3.5; ynose puede ejecutar correctamente en Python 2.7 o Python 3.5. Esto muestra que el módulo json tiene soporte limitado para la deserialización de tipos de datos personalizados, pero también podemos obtener un objeto dict a través de la función json.loads (JSON_STR) sin especificar el parámetro cls, y luego completar la conversión de dict a objeto por nosotros mismos .

Existe un efecto adicional al heredar JSONEncoder para lograr la serialización, es decir, un objeto de datos grande se puede serializar varias veces a través del método iterencode (), que es muy útil para escenarios como la transmisión de red y la persistencia del disco.

>>> for chunk in MyJSONEncoder().iterencode(stu):
...     print(chunk)
...
{
"__class__"
:
"Student"
,
"name"
:
"Tom"
,
"__module__"
:
"__main__"
,
"sno"
:
1
,
"age"
:
19
}

Pseudocódigo de transmisión de red de serialización de objetos de big data:

for chunk in JSONEncoder().iterencode(bigobject):
    mysocket.write(chunk)

Dos, módulo de pepinillos


El módulo pickle implementa un protocolo binario para la serialización y deserialización de estructuras de objetos de Python. A diferencia del módulo json, los procesos de serialización y deserialización del módulo pickle se denominan pickling y unickling:

  • Decapado:  es el proceso de convertir objetos Python en flujos de bytes;
  • Unpickling:  es el proceso de convertir archivos binarios de flujo de bytes u objetos de bytes de nuevo en objetos de Python;

1. Comparación del módulo pickle y el módulo json

  • JSON es un formato de serialización de texto (genera archivos unicode, la mayoría de las veces se codificará como utf-8) y pickle es un formato de serialización binario;
  • JOSN es un formato de datos que podemos entender, mientras que pickle es un formato binario que no podemos entender;
  • JSON no está relacionado con un lenguaje o sistema de programación específico, y se usa ampliamente fuera del ecosistema de Python, mientras que el formato de datos usado por pickle es específico de Python;
  • De forma predeterminada, JSON solo puede representar los tipos de datos integrados de Python. Para los tipos de datos personalizados, se requiere un poco de trabajo adicional para completar; pickle puede representar directamente una gran cantidad de tipos de datos de Python, incluidos los tipos de datos personalizados (muchos de los cuales son inteligentemente automáticamente implementado usando la función de introspección de Python; situaciones complejas se pueden resolver implementando API de objeto específico)

2. Formato de flujo de datos utilizado por el módulo pickle

Como se mencionó anteriormente, el formato de datos utilizado por pickle es específico de Python. Esto lo libera de límites estándar externos como JSON o XDR, pero también significa que es posible que los programas que no sean de Python no puedan reconstruir objetos de Python en escabeche. De forma predeterminada, el formato de datos pickle utiliza una representación binaria relativamente compacta. Si necesita la función de mejor tamaño, los datos decapados se pueden comprimir de manera efectiva. El módulo pickletools contiene herramientas que se pueden utilizar para analizar el flujo de datos generado por pickle. Actualmente existen 5 protocolos diferentes que se pueden utilizar para encurtidos. Cuanto mayor sea el protocolo utilizado, se necesita la versión actualizada de Python para leer los datos generados por pickle:

  • El protocolo v0 es el protocolo original "legible por humanos" y es compatible con versiones anteriores de Python;
  • El protocolo v1 es un formato binario antiguo que también es compatible con versiones anteriores de Python;
  • El protocolo v2 se introdujo en Python 2.3, que proporciona un decapado más eficiente;
  • El protocolo v3 es un protocolo agregado en Python 3.0. Claramente admite objetos de bytes y Python 2.x no puede eliminarlo; este es el protocolo predeterminado y el protocolo recomendado cuando se requiere compatibilidad con otras versiones de Python 3;
  • El protocolo 4 es un protocolo agregado en Python 3.4. Agrega soporte para objetos extremadamente grandes, decapado de más tipos de objetos y algunas optimizaciones de formato de datos.

Nota: El  protocolo v0 se usa de forma predeterminada en Python 2.x. Si el protocolo se especifica como asignación o HIGHEST_PROTOCOL, se usará la versión de protocolo más alta actualmente disponible; el protocolo v3 se usa de manera predeterminada en Python 3.x, que es compatible con otras versiones de Python 3. Pero no es compatible con Python 2.

Nota: La  serialización (serialización) es un concepto más primitivo que la persistencia (persistencia); aunquepicklelos objetos de archivo se pueden leer y escribir, no se ocupa del nombre de objetos persistentes, ni se ocupa del acceso concurrente a objetos persistentes (incluso más problemas complicados). pickleLos módulos pueden convertir objetos complejos en flujos de bytes y pueden convertir flujos de bytes en objetos con la misma estructura interna . Quizás lo más probable que pueda hacer con estos flujos de bytes es escribirlos en un archivo, pero también puede transferirlos a través de la red o almacenarlos en una base de datos. shelveEl módulo proporciona una interfaz simple para eliminar y eliminar objetos en archivos de base de datos de estilo DBM.

3. Funciones relacionadas proporcionadas por el módulo pickle

Varias funciones de serialización / deserialización proporcionadas por el módulo pickle son básicamente las mismas que las del módulo json:

# 将指定的Python对象通过pickle序列化作为bytes对象返回,而不是将其写入文件
dumps(obj, protocol=None, *, fix_imports=True)

# 将通过pickle序列化后得到的字节对象进行反序列化,转换为Python对象并返回
loads(bytes_object, *, fix_imports=True, encoding="ASCII", errors="strict")

# 将指定的Python对象通过pickle序列化后写入打开的文件对象中,等价于`Pickler(file, protocol).dump(obj)`
dump(obj, file, protocol=None, *, fix_imports=True)

# 从打开的文件对象中读取pickled对象表现形式并返回通过pickle反序列化后得到的Python对象
load(file, *, fix_imports=True, encoding="ASCII", errors="strict")

Nota: En los  varios parámetros de método anteriores, los parámetros después de * son todos nuevos en Python 3.x para compatibilidad con Python 2.x. Para un uso específico, consulte la documentación oficial.

4. Ejemplo: serialización / deserialización de tipos de datos integrados

Python 2.x

>>> import pickle
>>> 
>>> var_a = {'a':'str', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)}

# 序列化
>>> var_b = pickle.dumps(var_a)
>>> var_b
"(dp0\nS'a'\np1\nS'str'\np2\nsS'c'\np3\nI01\nsS'b'\np4\nF11.1\nsS'e'\np5\nI10\nsS'd'\np6\nNsS'g'\np7\n(I4\nI5\nI6\ntp8\nsS'f'\np9\n(lp10\nI1\naI2\naI3\nas."

# 反序列化
>>> var_c = pickle.loads(var_b)
>>> var_c
{'a': 'str', 'c': True, 'b': 11.1, 'e': 10, 'd': None, 'g': (4, 5, 6), 'f': [1, 2, 3]}

Python 3.x

>>> import pickle
>>>
>>> var_a = {'a':'str', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)}

# 序列化
>>> var_b = pickle.dumps(var_a)
>>> var_b
b'\x80\x03}q\x00(X\x01\x00\x00\x00eq\x01K\nX\x01\x00\x00\x00aq\x02X\x03\x00\x00\x00strq\x03X\x01\x00\x00\x00fq\x04]q\x05(K\x01K\x02K\x03eX\x01\x00\x00\x00gq\x06K\x04K\x05K\x06\x87q\x07X\x01\x00\x00\x00bq\x08G@&333333X\x01\x00\x00\x00cq\t\x88X\x01\x00\x00\x00dq\nNu.'

# 反序列化
>>> var_c = pickle.loads(var_b)
>>> var_c
{'e': 10, 'a': 'str', 'f': [1, 2, 3], 'g': (4, 5, 6), 'b': 11.1, 'c': True, 'd': None}

dump () 与 load ()

>>> import pickle
>>>
>>> var_a = {'a':'str', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)}

# 持久化到文件
>>> with open('pickle.txt', 'wb') as f:
...     pickle.dump(var_a, f)
...

# 从文件中读取数据
>>> with open('pickle.txt', 'rb') as f:
...     var_b = pickle.load(f)
...
>>> var_b
{'e': 10, 'a': 'str', 'f': [1, 2, 3], 'g': (4, 5, 6), 'b': 11.1, 'c': True, 'd': None}
>>>

Descripción:

  • De forma predeterminada, los datos después de encurtidos en Python 2.x tienen la forma de una cadena, y deben convertirse en un objeto de byte para ser deserializados por pickle.loads () en Python 3.x; usado por decapado en Python 3.x El protocolo es v3, por lo que debe especificar el protocolo de parámetro opcional al llamar a pickle.dumps () como la versión del protocolo compatible con Python 2.x (0,1,2); de lo contrario, los datos después de pickled no se pueden usar por Python 2.x La deserialización pickle.loads () en;
  • El objeto de archivo especificado en los métodos pickle.dump () y pickle.load () en Python 3.x debe abrirse en modo binario (rb, wb) , mientras que en Python 2.x, puede abrirse en modo binario o El modo de texto está activado.

5. Ejemplo: serialización / deserialización de tipos de datos personalizados

Primero personalice un tipo de datos:

class Student(object):
    def __init__(self, name, age, sno):
        self.name = name
        self.age = age
        self.sno = sno
    
    def __repr__(self):
        return 'Student [name: %s, age: %d, sno: %d]' % (self.name, self.age, self.sno)

El módulo pickle puede serializar / deserializar directamente tipos de datos personalizados sin escribir funciones o clases de procesamiento adicionales.

>>> stu = Student('Tom', 19, 1)
>>> print(stu)
Student [name: Tom, age: 19, sno: 1]

# 序列化
>>> var_b = pickle.dumps(stu)
>>> var_b
b'\x80\x03c__main__\nStudent\nq\x00)\x81q\x01}q\x02(X\x04\x00\x00\x00nameq\x03X\x03\x00\x00\x00Tomq\x04X\x03\x00\x00\x00ageq\x05K\x13X\x03\x00\x00\x00snoq\x06K\x01ub.'

# 反序列化
>>> var_c = pickle.loads(var_b)
>>> var_c
Student [name: Tom, age: 19, sno: 1]

# 持久化到文件
>>> with open('pickle.txt', 'wb') as f:
...     pickle.dump(stu, f)
...

# 从文件总读取数据
>>> with open('pickle.txt', 'rb') as f:
...     pickle.load(f)
...
Student [name: Tom, age: 19, sno: 1]

clear_memo ()
  borra el "memo" del pickler. Cuando se utiliza una instancia de Pickler para serializar un objeto, "recordará" la referencia del objeto que se ha serializado, por lo que si llama a dump (obj) varias veces en el mismo objeto, Pickler no lo serializará "tontamente" varias veces.

Módulo de tres estantes


Shelve es una solución de almacenamiento de datos simple, similar a una base de datos de valores clave, que puede guardar fácilmente objetos de Python, y sus datos internos se serializan a través del protocolo pickle. Shelve tiene solo una función open (), esta función se usa para abrir el archivo especificado (un diccionario persistente) y luego devolver un objeto de estantería. Un estante es un objeto persistente parecido a un diccionario. Se diferencia de "dbm" en que sus valores pueden ser cualquier objeto Python básico, cualquier dato que pueda manejar el módulo pickle. Esto incluye la mayoría de instancias de clases, tipos de datos recursivos y objetos que contienen muchos subobjetos compartidos. la clave debe ser una cadena.

open(filename, flag='c', protocol=None, writeback=False)

El  parámetro de bandera indica el formato del archivo de almacenamiento de datos que se abrirá y sus posibles valoresdbm.open()son consistentescon lafunción:

valor descripción
'r' Abra un archivo de almacenamiento de datos existente en modo de solo lectura
'w' Abra un archivo de almacenamiento de datos existente en modo lectura-escritura
'C' Abra un archivo de almacenamiento de datos en modo lectura-escritura, créelo si no existe
'norte' Cree siempre un archivo de almacenamiento de datos nuevo y vacío y ábralo en modo lectura-escritura

El  parámetro de protocolo indica la versión de protocolo utilizada para serializar los datos, el valor predeterminado es pickle v3;

El  parámetro de escritura diferida indica si se habilita la función de escritura diferida.

Podemos usar el objeto estante como un dict-store, cambiar y consultar los datos correspondientes a una clave.Cuando la operación se completa, llama a la función close () del objeto estante. Por supuesto, también puede usar el administrador de contexto (con declaración) para evitar llamar manualmente al método close () cada vez.

Ejemplo: operación de tipo de datos incorporada

# 保存数据
with shelve.open('student') as db:
    db['name'] = 'Tom'
    db['age'] = 19
    db['hobby'] = ['篮球', '看电影', '弹吉他']
    db['other_info'] = {'sno': 1, 'addr': 'xxxx'}

# 读取数据
with shelve.open('student') as db:
    for key,value in db.items():
        print(key, ': ', value)

Resultado de salida:

name :  Tom
age :  19
hobby :  ['篮球', '看电影', '弹吉他']
other_info :  {'sno': 1, 'addr': 'xxxx'}

Ejemplo: operación de tipo de datos personalizado

# 自定义class
class Student(object):
    def __init__(self, name, age, sno):
        self.name = name
        self.age = age
        self.sno = sno
    
    def __repr__(self):
        return 'Student [name: %s, age: %d, sno: %d]' % (self.name, self.age, self.sno)

# 保存数据
tom = Student('Tom', 19, 1)
jerry = Student('Jerry', 17, 2)

with shelve.open("stu.db") as db:
    db['Tom'] = tom
    db['Jerry'] = jerry

# 读取数据
with shelve.open("stu.db") as db:
    print(db['Tom'])
    print(db['Jerry'])

Resultado de salida:

Student [name: Tom, age: 19, sno: 1]
Student [name: Jerry, age: 17, sno: 2]

Cinco, resumen


1. Contraste

El módulo json se usa a menudo para escribir interfaces web para convertir datos de Python en un formato json común y pasarlo a otros sistemas o clientes; también se puede usar para guardar datos de Python en un archivo local. La desventaja es que se guarda en texto sin formato y tiene poca confidencialidad. Además, si necesita guardar tipos de datos no integrados, debe escribir funciones de conversión adicionales o clases personalizadas.

Debido a que el módulo pickle y el módulo shelf usan su protocolo de serialización único, los datos serializados solo pueden ser reconocidos por Python, por lo que solo pueden usarse dentro del sistema Python. Además, los
protocolos de serialización predeterminados utilizados por Python 2.xy Python 3.x también son diferentes. Si necesita ser compatible entre sí, debe especificar la versión del protocolo a través del parámetro de protocolo durante la serialización. Además de las deficiencias anteriores, la ventaja del módulo pickle y el módulo shelve sobre el módulo json es que puede serializar y deserializar directamente tipos de datos personalizados sin escribir funciones o clases de conversión adicionales.

El módulo de estantería se puede considerar como una versión mejorada del módulo de salmuera, porque estantería utiliza el protocolo de serialización de la salmuera, pero estantería es más simple y más conveniente que la operación proporcionada por pickle. En comparación con los otros dos módulos, el módulo shelve tiene una ventaja obvia a la hora de conservar los datos de Python en el disco local. Nos permite manipular los datos serializados como un dictado sin tener que guardarlos o leerlos todos a la vez. Todos los datos.

2. Sugerencias

  • Utilice el módulo json cuando necesite interactuar con sistemas externos;
  • Cuando necesite conservar una pequeña cantidad de datos simples de Python en un archivo de disco local, puede considerar usar el módulo pickle;
  • Cuando necesite conservar una gran cantidad de datos de Python en un archivo de disco local o necesite algunas funciones simples de adición, eliminación, modificación y consulta similares a las de una base de datos, puede considerar usar el módulo shelve.

3. Apéndice

Función a realizar API que se pueden utilizar
Convierta el tipo de datos de Python en una cadena (json) json.dumps ()
Convierta la cadena json al tipo de datos Python json.loads ()
Guarde el tipo de datos de Python en el disco local en forma de json json.dump ()
Convierta los datos json en el archivo de disco local al tipo de datos Python json.load ()
Convierta los tipos de datos de Python a un formato binario específico de Python pickle.dumps ()
Convierta datos de formato binario específicos de Python en tipos de datos de Python pickle.loads ()
Guarde el tipo de datos de Python en el disco local en un formato binario específico de Python pickle.dump ()
将本地磁盘文件中的Python特定的二进制格式数据转换为Python数据类型 pickle.load()
以类型dict的形式将Python数据类型保存到本地磁盘或读取本地磁盘数据并转换为数据类型 shelve.open()

Supongo que te gusta

Origin blog.csdn.net/zangba9624/article/details/108658756
Recomendado
Clasificación