Wie man ein Objekt entpackt, dessen Klasse in einem anderen Namespace (Python) existiert?

9

Wenn ich ein Skript habe, das eine Klasse definiert:

%Vor%

und führen Sie dann dieses Skript in seinem eigenen Namespace dict:

aus %Vor%

und dann erstellen Sie eine Instanz der Klasse und pickle es:

%Vor%

Wenn ich jetzt versuche, es zu entpacken:

%Vor%

Ich bekomme den Fehler

%Vor%

Ich nehme an, dass das nicht funktioniert, weil Python nicht weiß, wo myClass zu finden ist, um das Objekt neu zu erstellen. Aber meine Klasse existiert im NS-Diktat. Gibt es eine Möglichkeit, Pickle zu sagen, wo die Klasse für das Objekt zu finden ist, das geladen wird?

    
user1804375 09.01.2013, 15:36
quelle

2 Antworten

2

Ich habe eine Lösung gefunden. Es scheint, als ob das Ausführen von Code in einem Diktat Python daran hindert herauszufinden, wo die Klasse definiert ist. Die Lösung besteht darin, ein leeres Modul zu erstellen, den Code im Modul auszuführen und dann das Modul zu sys.modules hinzuzufügen, damit Python davon erfährt.

%Vor%

Jetzt ist es möglich, eine Instanz der Klasse zu pickle und unpickle:

%Vor%     
user1804375 09.01.2013, 20:12
quelle
3

Sie können sogar noch einen Schritt weiter gehen und das Objekt sich in den von Ihnen gewünschten Typ rekonstruieren lassen.

%Vor%

Die Grundidee ist, dass Sie Ihre Klasse in ein "Trojanisches Pferd" packen, wo ihre Rekonstruktion eine Instanziierung einer anderen Klasse verursacht, als sie ursprünglich war.

Es spielt keine Rolle, was die otherclass auf der Beizseite enthält. Es kommt nur darauf an, dass es im selben Modulpfad wie die "Ziel" -Klasse existiert - pickle fügt nur eine String-Repräsentation des Modulnamens in den serialisierten Stream ein.

Also, um zu brechen, was im obigen Code passiert, im Detail:

  • Wir registrieren einen benutzerdefinierten Abbeizer für myClass . Dies kann über copy_reg oder die Funktion __reduce_ex__ erfolgen.
  • Unser benutzerdefinierter Abbeißer sagt "pickle dies als eine Instanz von otherclass " (was ein Dummy ist. Sie nicht brauchen den "echten" Inhalt von otherclass auf der Beizseite, weil Alles, was in die Gurke geht, ist der Modul- / Klassenname.
  • Wir pikken das Objekt und "senden es über die Leitung" dorthin, wo die echte Version von otherclass existiert.
  • Auf der Remoteseite wird otherclass mit den Daten aus dem Tupel instanziiert, die von der benutzerdefinierten Beizfunktion zurückgegeben werden.

Python kann ziemlich mächtig sein!

    
Borealid 09.01.2013 16:17
quelle

Tags und Links