Si può decidere ed attuare come qualsiasi tipo precedentemente unpicklable viene decapato e deserializzato: vedi libreria standard modulo copy_reg (rinominato in copyreg
in Python 3. *).
In sostanza, è necessario fornire una funzione che, data un'istanza del tipo, la riduca a una tupla - con lo stesso protocollo del metodo speciale reduce (tranne che il metodo speciale Riduci non accetta argomenti, dal momento che purché sia chiamato direttamente sull'oggetto, mentre la funzione fornita prenderà l'oggetto come unico argomento).
In genere, la tupla restituita contiene 2 elementi: un callable e una tupla di argomenti da passare ad esso. Il callable deve essere registrato come "costruttore sicuro" o avere equivalentemente un attributo __safe_for_unpickling__
con un valore reale. Questi oggetti saranno messi in salamoia, e al momento del disimpegno il callable sarà chiamato con gli argomenti dati e dovrà restituire l'oggetto non selezionato. Ad esempio, supponiamo di voler semplicemente sottoporre a pickle i moduli per nome, in modo che deselezionarli significhi reimportarli (supponiamo per semplicità che non ti interessino i moduli modificati dinamicamente, i pacchetti nidificati, ecc, solo semplici moduli di livello superiore).Poi:
>>> import sys, pickle, copy_reg
>>> def savemodule(module):
... return __import__, (module.__name__,)
...
>>> copy_reg.pickle(type(sys), savemodule)
>>> s = pickle.dumps(sys)
>>> s
"c__builtin__\n__import__\np0\n(S'sys'\np1\ntp2\nRp3\n."
>>> z = pickle.loads(s)
>>> z
<module 'sys' (built-in)>
Sto utilizzando il modulo vecchio stile ASCII di salamoia in modo che s
, la stringa contenente la salamoia, è facile da esaminare: si incarica deserializzazione di chiamare il built-in funzione di importazione, con la stringa sys
come argomento esclusivo. E z
dimostra che questo ci restituisce il modulo integrato sys
come risultato del non prelievo, come desiderato.
Ora, dovrai rendere le cose un po 'più complesse del solo __import__
(dovrai occuparti di salvare e ripristinare le modifiche dinamiche, navigare in uno spazio dei nomi annidato, ecc.) E quindi dovrai anche chiama copy_reg.constructor
(passando come argomento la propria funzione che esegue questo lavoro) prima di copy_reg
la funzione di risparmio del modulo che restituisce l'altra funzione (e, se in una corsa separata, anche prima di deselezionare quei sottaceti che hai fatto usando detta funzione). Ma spero che questo semplice caso contribuisca a dimostrare che non c'è davvero niente di tutto ciò che è "intrinsecamente" complicato! -)
Java Beans .. Python Pickles .. Mi piacerebbe strozzare i nerd che escono con questo roba cutesy –