Sono il dill
autore. Faccio esattamente questa cosa su ssh
, ma con successo. Attualmente, dill
e uno degli altri serializzatori moduli pickle per riferimento ... quindi per passare con successo una funzione definita in un file, è necessario assicurarsi che il modulo pertinente sia installato anche sull'altra macchina. Non credo ci sia alcun serializzatore di oggetti che serializza direttamente i moduli (cioè non per riferimento).
Detto questo, dill
ha alcune opzioni per serializzare le dipendenze degli oggetti. Ad esempio, per le istanze di classe, il valore predefinito in dill
consiste nel non serializzare le istanze di classe per riferimento ... in modo che la definizione di classe possa anche essere serializzata e inviare con l'istanza. In dill
, è anche possibile (utilizzare una funzionalità molto nuova per) serializzare gli handle di file serializzando il file, invece di farlo per riferimento. Ma di nuovo, se si ha il caso di una funzione definita in un modulo, si è sfortunati, poiché i moduli sono serializzati per riferimento universalmente malissimo.
Potrebbe essere possibile utilizzare dill
per farlo, tuttavia, non solo con il decapaggio dell'oggetto, ma con l'estrazione dell'origine e l'invio del codice sorgente. In pathos.pp
, dill
, per estrarre la fonte e le dipendenze di qualsiasi oggetto (comprese le funzioni) e passarle a un altro computer/processo/ecc. Tuttavia, poiché questa non è una cosa facile da fare, dill
può anche utilizzare il failover del tentativo di estrarre un'importazione rilevante e inviarlo invece del codice sorgente.
Si può capire, si spera, questa è una cosa caotica e disordinata da fare (come indicato in una delle dipendenze della funzione che sto estrapolando di seguito). Tuttavia, ciò che si sta chiedendo viene eseguito con successo nel pacchetto pathos
per passare il codice e le dipendenze a macchine diverse attraverso le porte con tunnel ssh.
>>> import dill
>>>
>>> print dill.source.importable(dill.source.importable)
from dill.source import importable
>>> print dill.source.importable(dill.source.importable, source=True)
def _closuredsource(func, alias=''):
"""get source code for closured objects; return a dict of 'name'
and 'code blocks'"""
#FIXME: this entire function is a messy messy HACK
# - pollutes global namespace
# - fails if name of freevars are reused
# - can unnecessarily duplicate function code
from dill.detect import freevars
free_vars = freevars(func)
func_vars = {}
# split into 'funcs' and 'non-funcs'
for name,obj in list(free_vars.items()):
if not isfunction(obj):
# get source for 'non-funcs'
free_vars[name] = getsource(obj, force=True, alias=name)
continue
# get source for 'funcs'
#…snip… …snip… …snip… …snip… …snip…
# get source code of objects referred to by obj in global scope
from dill.detect import globalvars
obj = globalvars(obj) #XXX: don't worry about alias?
obj = list(getsource(_obj,name,force=True) for (name,_obj) in obj.items())
obj = '\n'.join(obj) if obj else ''
# combine all referred-to source (global then enclosing)
if not obj: return src
if not src: return obj
return obj + src
except:
if tried_import: raise
tried_source = True
source = not source
# should never get here
return
immagino cosa potrebbe anche essere costruito attorno al metodo dill.detect.parents
, che fornisce un elenco di puntatori a tutti oggetto padre per un dato oggetto ... e si potrebbe ricostruire tutte le dipendenze di ogni funzione come oggetti ... ma questo non è implementato.
BTW: per stabilire un tunnel ssh, basta fare questo:
>>> t = pathos.Tunnel.Tunnel()
>>> t.connect('login.university.edu')
39322
>>> t
Tunnel('-q -N -L39322:login.university.edu:45075 login.university.edu')
Poi si può lavorare attraverso la porta locale con ZMQ
, o ssh
, o qualsiasi altra cosa. Se si desidera farlo con ssh
, anche pathos
ha incorporato quello.
È una cosa facile da fare per sostituire il nome del modulo di una funzione al momento dello scaricamento. Durante la serializzazione, è possibile sostituire qualsiasi '__name__' con' __main__', e voilà ... dovrebbe funzionare ... cioè, a meno che la funzione non abbia ** eventuali ** dipendenze nel modulo allegato. Allora fallirà. –
Il problema è che il file dill.loads ha esito negativo, non viene mai annullato. Come indicato correttamente nel post sottostante, poiché nell'esempio precedente non è disponibile, i carichi muoiono. Quindi rinominarlo dopo il fatto non aiuta. –
Prasanna
Non sto parlando di ridenominarlo dopo il fatto, sto parlando di sostituire l'attributo al momento del caricamento con un pickler personalizzato. Quello funzionerebbe come sopra dettagliato. –