Vorrei passare lo stato oggetto tra due programmi Python (uno è il mio codice in esecuzione standalone, uno è una vista Pyramid) e diversi spazi dei nomi. Le domande un po 'correlate sono here o here, ma non riesco a seguirle abbastanza per il mio scenario.Archiviare oggetto usando Pickle Python e caricarlo in uno spazio dei nomi diverso
mio codice definisce una classe globale (cioè __main__
namespace) di struttura piuttosto complexish:
# An instance of this is a colorful mess of nested lists and sets and dicts.
class MyClass :
def __init__(self) :
data = set()
more = dict()
...
def do_sth(self) :
...
A un certo punto pickle un'istanza di questa classe:
c = MyClass()
# Fill c with data.
# Pickle and write the MyClass instance within the __main__ namespace.
with open("my_c.pik", "wb") as f :
pickle.dump(c, f, -1)
A hexdump -C my_c.pik
mostra che la prima coppia di byte contiene __main__.MyClass
da cui presumo che la classe sia effettivamente definita nel namespace globale e che questo sia in qualche modo un requisito per leggere il pickle. Ora vorrei caricare questo salamoia MyClass
esempio all'interno di una piramide vista, che presumo è uno spazio dei nomi diverso:
# In Pyramid (different namespace) read the pickled MyClass instance.
with open("my_c.pik", "rb") as f :
c = pickle.load(f)
Ma che genera il seguente errore:
File ".../views.py", line 60, in view_handler_bla
c = pickle.load(f)
AttributeError: 'module' object has no attribute 'MyClass'
Sembra me che la definizione MyClass
manca in qualsiasi spazio dei nomi che viene eseguito dal codice di visualizzazione? Speravo (presumevo) che il decapaggio fosse un processo un po 'opaco che mi permettesse di leggere un blob di dati nel luogo che ho scelto. (Maggiori informazioni sui nomi delle classi e gli spazi dei nomi di Python sono here.)
Come posso gestirlo correttamente? (Idealmente senza dover importare cose attraverso ...) Posso in qualche modo trovare lo spazio dei nomi corrente e iniettare MyClass
(come sembra suggerire la risposta this)?
Poor Soluzione
Mi sembra che se mi astengo dal definire e utilizzare MyClass
e invece ricadere a semplici tipi di dati built-in, questo non sarebbe un problema. Infatti, ho potuto "serializzare" l'oggetto MyClass
in una sequenza di chiamate che Pickle i singoli elementi dell'istanza MyClass
:
# 'Manual' serialization of c works, because all elements are built-in types.
pickle.dump(c.data, f, -1)
pickle.dump(c.more, f, -1)
...
Questo sarebbe annullare l'obiettivo di incarto dati in classi però.
Nota
decapaggio si occupa solo dello stato di una classe, non di eventuali funzioni definite nell'ambito della classe (es do_sth()
nell'esempio precedente). Ciò significa che il caricamento di un'istanza MyClass
in uno spazio dei nomi diverso senza la definizione di classe appropriata carica solo i dati dell'istanza; chiamare una funzione mancante come do_sth()
causerà un AttributeError.
hai pensato di usare [tuple di nome] (http: // StackOverflow. com/domande/2970608/cosa-sono-nome-tuple-in-Python)? Dovrebbero essere anche selezionabili. – User
@User: Sarebbe parte della "soluzione scadente" sopra la quale ricado ai tipi più semplici. Sì, l'ho provato e funziona. Ma questa è una soluzione alternativa evitante, non una risposta alla mia domanda ;-) – Jens
Potresti semplicemente definire 'MyClass' in un modulo diverso da' __main__' ... il tuo primo programma dovrebbe usare qualche modulo personalizzato per definire quella classe, e poi devi solo aggiungerlo al percorso per il secondo programma. – Bakuriu