Você poderia serializar o bytecode da função e, em seguida, reconstruí-lo no chamador. O módulo marshal pode ser usado para serializar objetos de código, que podem ser remontados em uma função. ie:
import marshal
def foo(x): return x*x
code_string = marshal.dumps(foo.func_code)
Então, no processo remoto (após transferir code_string):
import marshal, types
code = marshal.loads(code_string)
func = types.FunctionType(code, globals(), "some_func_name")
func(10) # gives 100
Algumas advertências:
O formato do marshal (qualquer bytecode python para esse assunto) pode não ser compatível entre as versões principais do python.
Só funcionará para implementação de cpython.
Se a função faz referência a globais (incluindo módulos importados, outras funções, etc.) que você precisa selecionar, será necessário serializá-los também ou recriá-los no lado remoto. Meu exemplo apenas fornece o namespace global do processo remoto.
Você provavelmente precisará fazer um pouco mais para oferecer suporte a casos mais complexos, como encerramentos ou funções de gerador.
marshal
módulo para serializar um dicionário de dicionários inicializado comodefaultdict(lambda : defaultdict(int))
. Mas retorna o erroValueError: unmarshallable object
. Observe que estou usando o python2.7. Qualquer ideia? Obrigadofoo.func_code
aumentaAttributeError
. Existe outra maneira de obter o código da função?Confira Dill , que estende a biblioteca pickle do Python para oferecer suporte a uma grande variedade de tipos, incluindo funções:
Ele também oferece suporte a referências a objetos no encerramento da função:
fonte
O Pyro pode fazer isso por você .
fonte
A maneira mais simples é provavelmente
inspect.getsource(object)
(consulte o módulo inspect ) que retorna uma String com o código-fonte de uma função ou método.fonte
Tudo depende se você gera a função em tempo de execução ou não:
Se você fizer isso -
inspect.getsource(object)
não funcionará para funções geradas dinamicamente, uma vez que obtém a fonte do objeto do.py
arquivo, portanto, apenas as funções definidas antes da execução podem ser recuperadas como fonte.E se suas funções são colocadas em arquivos de qualquer maneira, por que não dar ao receptor acesso a eles e apenas passar nomes de módulos e funções.
A única solução para funções criadas dinamicamente que posso pensar é construir a função como uma string antes da transmissão, transmitir a fonte e, em seguida
eval()
, no lado do receptor.Editar: a
marshal
solução também parece muito inteligente, não sabia que você pode serializar algo que não seja integradofonte
O
cloud
pacote (pip install cloud) pode selecionar código arbitrário, incluindo dependências. Consulte https://stackoverflow.com/a/16891169/1264797 .fonte
Agora
fonte
Você consegue fazer isso:
Agora,
transmit(fn_generator())
enviará a definição real de emfn(x,y)
vez de uma referência ao nome do módulo.Você pode usar o mesmo truque para enviar classes pela rede.
fonte
As funções básicas usadas para este módulo abrangem sua consulta, além de obter a melhor compactação durante a transmissão; veja o código fonte instrutivo:
y_serial.py module :: warehouse objetos Python com SQLite
"Serialização + persistência :: em algumas linhas de código, comprima e anote objetos Python em SQLite; depois recupere-os cronologicamente por palavras-chave sem qualquer SQL. Módulo" padrão "mais útil para um banco de dados para armazenar dados sem esquema."
http://yserial.sourceforge.net
fonte
Cloudpickle é provavelmente o que você está procurando. Cloudpickle é descrito da seguinte maneira:
Exemplo de uso:
fonte
Aqui está uma classe auxiliar que você pode usar para agrupar funções a fim de torná-las selecionáveis. As advertências já mencionadas para
marshal
serão aplicadas, mas um esforço é feito para usar picles sempre que possível. Nenhum esforço é feito para preservar globais ou encerramentos na serialização.fonte