with saving open loads how example python function pickle

python - saving - pickle.loads example



¿Hay alguna manera fácil de extraer una función de python(o serializar su código de otra manera)? (8)

Echa un vistazo a Dill , que amplía la biblioteca de pickle de Python para admitir una mayor variedad de tipos, incluidas funciones:

>>> import dill as pickle >>> def f(x): return x + 1 ... >>> g = pickle.dumps(f) >>> f(1) 2 >>> pickle.loads(g)(1) 2

También admite referencias a objetos en el cierre de la función:

>>> def plusTwo(x): return f(f(x)) ... >>> pickle.loads(pickle.dumps(plusTwo))(1) 3

Estoy tratando de transferir una función a través de una conexión de red (usando asyncore). ¿Existe una manera fácil de serializar una función de Python (una que, al menos en este caso, no tendrá efectos secundarios) para una transferencia como esta?

Idealmente me gustaría tener un par de funciones similares a estas:

def transmit(func): obj = pickle.dumps(func) [send obj across the network] def receive(): [receive obj from the network] func = pickle.loads(s) func()


El paquete de cloud (nube de instalación de pip) puede recortar el código arbitrario, incluidas las dependencias. Ver https://.com/a/16891169/1264797 .


La forma más simple es probablemente inspect.getsource(object) (ver el módulo de inspección ) que devuelve una Cadena con el código fuente de una función o método.


Las funciones básicas utilizadas para este módulo cubren su consulta, además de obtener la mejor compresión sobre el cable; ver el código fuente instructivo:

y_serial.py module :: warehouse Python objects with SQLite

"Serialización + persistencia :: en unas pocas líneas de código, comprima y anote objetos de Python en SQLite, y luego recupérelos cronológicamente por palabras clave sin ningún SQL. Módulo" estándar "más útil para que una base de datos almacene datos sin esquema".

http://yserial.sourceforge.net


Puede serializar el bytecode de la función y luego reconstruirlo en la persona que llama. El módulo marshal se puede utilizar para serializar objetos codificados, que luego se pueden volver a ensamblar en una función. es decir:

import marshal def foo(x): return x*x code_string = marshal.dumps(foo.func_code)

Luego en el proceso remoto (después de transferir code_string):

import marshal, types code = marshal.loads(code_string) func = types.FunctionType(code, globals(), "some_func_name") func(10) # gives 100

Algunas advertencias:

  • El formato de Marshal (cualquier bytecode de Python para el caso) puede no ser compatible entre las principales versiones de Python.

  • Solo funcionará para la implementación de cpython.

  • Si la función hace referencia a los elementos globales (incluidos los módulos importados, otras funciones, etc.) que debe recoger, deberá serializarlos también o recrearlos en el lado remoto. Mi ejemplo simplemente le da el espacio de nombre global del proceso remoto.

  • Probablemente necesites hacer un poco más para soportar casos más complejos, como cierres o funciones del generador.


Todo depende de si genera la función en tiempo de ejecución o no:

Si lo hace, inspect.getsource(object) no funcionará para las funciones generadas dinámicamente, ya que obtiene el origen del objeto desde el archivo .py , por lo que solo las funciones definidas antes de la ejecución se pueden recuperar como fuente.

Y si sus funciones se colocan en archivos de todos modos, ¿por qué no darles acceso al receptor y solo pasar nombres de módulos y funciones?

La única solución para las funciones creadas dinámicamente que puedo pensar es construir la función como una cadena antes de la transmisión, la fuente de transmisión y luego eval() en el lado del receptor.

Editar: la solución Marshal también parece bastante inteligente, no sabía que podía serializar algo que no estuviera incorporado



code_string = '''''' def foo(x): return x * 2 def bar(x): return x ** 2 '''''' obj = pickle.dumps(code_string)

Ahora

exec(pickle.loads(obj)) foo(1) > 2 bar(3) > 9