[Spinning Up] Un artículo para comprender los módulos de serialización json, pickle y cloudpickle

[Spinning Up] Un artículo para comprender los módulos de serialización json, pickle y cloudpickle

Prefacio:

Recientemente, pasé mucho tiempo analizando el módulo paralelo multiproceso de spinning. Como no tengo la base relevante, el documento oficial también se omite aquí.
Incluso hay muy pocos blogs de terceros, lo que me hace un dolor de cabeza.
Por lo tanto, solo puede tomarse la molestia de averiguar cada oración de su módulo paralelo ...

Hace algún tiempo, vi mpi4py, subprocess, decorator, lambda y otras campanas y silbidos.

¿Por qué es necesaria esta operación? Publicaré un párrafo del contenido del próximo blog ~

Primero serialice la función thunk a través de cloudpickle.dumps y codifíquela en un archivo binario;
este archivo binario se puede decodificar en la función original a través de pickle.loads, y los parámetros permanecen sin cambios.
¿Qué función es la función,
pero por qué es costoso completar esta operación?
Porque si ejecuta DDPG-tf1, TD3-tf1 continuamente bajo el script actual, se reportará un error, porque
las variables del DDPG anterior en el proceso actual no se han borrado, por lo que se reporta el siguiente error:
ValueError: Variable main / pi / dense / kernel ya existe, no permitido.
Esto es muy vergonzoso. No tengo un buen plan para borrar las variables antes del proceso actual;
por lo tanto, tuve que agregar la función empaquetada que viene con spinup + un solo hiperparámetro -> iniciar subproceso -> decodificar -> Una función que ejecuta un solo hiperparámetro en el proceso hijo

Hoy es el turno de Pickle.

Introducción:

pickle: La traducción al inglés es pickle, que significa encurtido.

Su función es de hecho muy similar. Lo vi en Zhihu y alguien lo describió:

Qué es la serialización (serialización)
Cada lenguaje de programación tiene su propio tipo de datos, que convierte el tipo de datos o el objeto que pertenece a su propio lenguaje en un formato de datos que se puede transmitir a través de la red o almacenar en el disco local (como: XML, JSON o un formato específico) El proceso de cadena de bytes) se llama serialización; el inverso se llama deserialización.

Pero json solo puede manejar tipos de datos básicos y no es competente para objetos de función y objetos de clase.
Por tanto, se necesita un módulo más potente:

En este momento, el módulo Pickle es útil, puede convertir el objeto a un formato que se puede transmitir o almacenar.
Cloudpickle permite serializar construcciones de Python que no son compatibles con el módulo pickle predeterminado de la biblioteca estándar de Python.
Es decir, la función de pickle se expande, por lo que algunos otros tipos de datos también se pueden serializar.

Para los dos módulos de json y pickle, básicamente solo necesitas recordar el rol de las cuatro funciones;

Muchos artículos que leo son comentarios de código, pero no son lo suficientemente intuitivos. Es mejor cargar las rutinas, ver el resultado de las rutinas y agregar un pequeño comentario para obtener una comprensión profunda y su uso ~

Código de muestra:

1. La diferencia de codificación entre json y pickle (función .dumps ()):

import pickle
import json

outs = {
    
    "time": 12,
        "q_time": 1,
        "pi_time": 2}

# json和pickle的区别:
# 序列化一个对象为JSON格式,输出为字符串.
# dumps的直译是倾倒,用编码来理解,有点牵强~
outs_json_dumps = json.dumps(outs)
print("outs_json_dumps:", outs_json_dumps)

outs_pickle_dumps = pickle.dumps(outs)
print("outs_pickle_dumps:", outs_pickle_dumps)

打印 结果 :
outs_json_dumps: {“pi_time”: 2, “q_time”: 1, “time”: 12}
outs_pickle_dumps: b '\ x80 \ x03} q \ x00 (X \ x07 \ x00 \ x00 \ x00pi_timeq \ x01K \ x02X \ x06 \ x00 \ x00 \ x00q_timeq \ x02K \ x01X \ x04 \ x00 \ x00 \ x00timeq \ x03K \ x0cu. '

Se puede ver que el tipo de datos del diccionario se puede codificar. Después de que la codificación json es un tipo de cadena, el contenido de los datos se puede juzgar intuitivamente, ¡por lo que es más seguro !
Pero las cosas codificadas en pickle están en formato binario y es imposible ver qué demonios hay dentro.
Por lo tanto, no es lo suficientemente seguro. Los documentos oficiales sugieren que no debe abrir fácilmente un archivo de codificación desconocido ~

2. json no puede codificar objetos especiales, como funciones y clases:

Función de serialización ~

import pickle
import json

def foo(**kwargs):
    for key, value in kwargs.items():
        print("%s=%s" % (key, value))

# json和pickle的区别:
foo_pickle_dumps = pickle.dumps(foo)
print("foo_pickle_dumps:", foo_pickle_dumps)

foo_json_dumps = json.dumps(foo)
print("foo_json_dumps:", foo_json_dumps)

打印 结果 :
foo_pickle_dumps: b '\ x80 \ x03c__main __ \ nfoo \ nq \ x00.'
Traceback (última llamada más reciente):
Archivo “f: /rl_code/calibration/pickle_demo.py”, línea 17, en
foo_json_dumps = json.dumps (foo)
Archivo “D: \ Users \ lele \ Anaconda3 \ envs \ keras \ lib \ json_ init _.py ”, línea 230, en volcados
return _default_encoder.encode (obj)
Archivo“ D: \ Users \ lele \ Anaconda3 \ envs \ keras \ lib \ json \ encoder.py ”, línea 198, en
trozos de codificación = self.iterencode (o, _one_shot = True)
Archivo "D: \ Users \ lele \ Anaconda3 \ envs \ keras \ lib \ json \ encoder.py", línea 256, en iterencode
return _iterencode (o, 0)
Archivo "D : \ Users \ lele \ Anaconda3 \ envs \ keras \ lib \ json \ encoder.py ”, línea 179, por defecto
raise TypeError (repr (o) + "no es JSON serializable")
TypeError: <function foo at 0x0000016F7C2979D8> no es JSON serializable

Se puede ver que pickle no tiene presión y aún se puede ajustar, pero json no lo admite.
Solo debemos recordar que json solo puede codificar objetos de tipo de datos comunes, como diccionarios, listas y tuplas;

Tres, el objeto de carga de pepinillos:

Usa la función pickle.loads ()

import pickle
import json

def foo():
    print("hello world")
    
foo_pickle_dumps = pickle.dumps(foo)
print("foo_pickle_dumps:", foo_pickle_dumps)

foo_pickle_dumps_loads = pickle.loads(foo_pickle_dumps)
print("foo_pickle_dumps_loads:", foo_pickle_dumps_loads)

foo_pickle_dumps_loads()

打印 结果 :
foo_pickle_dumps: b '\ x80 \ x03c__main __ \ nfoo \ nq \ x00.'
foo_pickle_dumps_loads: <función foo en 0x00000214A4ABB488>
hola mundo

Se puede ver que después de que la función codificada por dumps () se vuelve binaria y luego decodificada por pickle.loads (), se convierte en una función seria y viviente.

4. La diferencia entre pickle.dumps () y pickle.dump (), y la diferencia entre pickle.loads () y pickle.load ();

No hay nada que decir al respecto, con la adición de s, los parámetros pasados ​​no necesitan una ruta, es decir, no necesitan ser guardados o leídos localmente.
Si no se agrega s, agregue la ruta ~
rutina:

import pickle
import json

def foo():
    print("hello world")

# json和pickle的区别:
with open("foo_pickle_dump.pkl", 'wb') as f:
    pickle.dump(obj=foo, file=f)
print("save sucess!")
foo_pickle_dump_load = pickle.load(open('foo_pickle.pkl', 'rb'))
print("foo_pickle_dump_load:", foo_pickle_dump_load)
foo_pickle_dump_load()

Resultado de impresión:
guardar éxito!
Foo_pickle_dump_load: <función foo en 0x0000017F30057AE8>
hola mundo

El archivo guardado localmente es un archivo foo_pickle_dump.pkl, que se distorsiona
después de abrirse; después de cargar, puede ver el nombre de la función foo, lo cual es genial ~

para resumir:

Hasta ahora, básicamente se puede considerar como un artículo para comprender el pickle;
esto se puede considerar como una parte importante del análisis de código dinámico.

Detalles de contacto

ps: Bienvenidos estudiantes que son intensivos para unirse al grupo para estudiar juntos:

Aprendizaje de refuerzo profundo-DRL: 799378128

Bienvenido a seguir la cuenta de Zhihu: aprendices de alquimia que aún no han comenzado

Cuenta CSDN: https://blog.csdn.net/hehedadaq

Supongo que te gusta

Origin blog.csdn.net/hehedadaq/article/details/114339620
Recomendado
Clasificación