Puede serializar el código de bytes de la función y luego reconstruirlo en la persona que llama. El módulo marshal se puede utilizar para serializar objetos de código, 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 código de bytes 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 globales (incluidos módulos importados, otras funciones, etc.) que necesita recoger, deberá serializarlos también o recrearlos en el lado remoto. Mi ejemplo simplemente le da el espacio de nombres global del proceso remoto.
Probablemente deba hacer un poco más para admitir casos más complejos, como cierres o funciones de generador.
marshal
módulo para serializar un diccionario de diccionarios inicializados comodefaultdict(lambda : defaultdict(int))
. Pero devuelve el errorValueError: unmarshallable object
. Tenga en cuenta que estoy usando python2.7. ¿Alguna idea? Graciasfoo.func_code
aumentaAttributeError
. ¿Existe otra forma de obtener el código de función?Consulte Dill , que amplía la biblioteca pickle de Python para admitir una mayor variedad de tipos, incluidas funciones:
También admite referencias a objetos en el cierre de la función:
fuente
Pyro puede hacer esto por usted .
fuente
La forma más sencilla 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.fuente
Todo depende de si genera la función en tiempo de ejecución o no:
Si lo hace
inspect.getsource(object)
, no funcionará para funciones generadas dinámicamente, ya que obtiene la fuente del objeto del.py
archivo, 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 dar acceso al receptor a ellas y solo pasar los nombres de los módulos y las funciones?
La única solución para las funciones creadas dinámicamente que se me ocurre 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
marshal
solución también parece bastante inteligente, no sabía que podía serializar algo más que los incorporadosfuente
El
cloud
paquete (pip install cloud) puede seleccionar código arbitrario, incluidas las dependencias. Consulte https://stackoverflow.com/a/16891169/1264797 .fuente
Ahora
fuente
Puedes hacerlo:
Ahora,
transmit(fn_generator())
enviará la definición real de enfn(x,y)
lugar de una referencia al nombre del módulo.Puede utilizar el mismo truco para enviar clases a través de la red.
fuente
Las funciones básicas utilizadas para este módulo cubren su consulta, además de que obtiene la mejor compresión por cable; ver el código fuente instructivo:
Módulo y_serial.py :: almacén de objetos Python con SQLite
"Serialización + persistencia :: en unas pocas líneas de código, comprima y anote objetos Python en SQLite; luego recupérelos cronológicamente por palabras clave sin SQL. El módulo" estándar "más útil para una base de datos para almacenar datos sin esquema".
http://yserial.sourceforge.net
fuente
Cloudpickle es probablemente lo que estás buscando. Cloudpickle se describe de la siguiente manera:
Ejemplo de uso:
fuente
Aquí hay una clase de ayuda que puede usar para ajustar funciones a fin de hacerlas seleccionables. Se
marshal
aplicarán las advertencias ya mencionadas , pero se hace un esfuerzo para usar pickle siempre que sea posible. No se hace ningún esfuerzo para preservar globales o cierres a través de la serialización.fuente