2010-04-13 11 views
5

Gibt es eine Möglichkeit, eine Klassendefinition zu putzen?Beizen einer Klassendefinition

Was ich tun möchte ist, die Definition (die dynamisch erstellt werden kann) zu picken, und dann über eine TCP-Verbindung zu senden, so dass eine Instanz am anderen Ende erstellt werden kann.

Ich verstehe, dass es Abhängigkeiten wie Module und globale Variablen geben kann, auf denen die Klasse beruht. Ich möchte diese auch im Beizprozess bündeln, aber ich bin nicht besorgt über die automatische Erkennung der Abhängigkeiten, weil es in Ordnung ist, wenn der Benutzer sie angeben muss.

+0

ich das gefunden, die den ganzen Interpreter Zustand Pickles: http://dev.pocoo.org/hg/sandbox/file/tip/pshell.py Klassendefinitionen scheinen auch in Ordnung zu sein ... – Giorgio

Antwort

2

Ach, nicht direkt. Sie können das Zeichenformular der class-Anweisung oder ein Bytecode-Formular senden und es auf der Empfängerseite mit einem exec "rehydrieren".

+0

Beziehen Sie sich darauf, nur die .py oder .pyc Dateien zu senden, die die Klassenanweisung enthalten? – Giorgio

+1

@Giorgio, Sie müssen nicht unbedingt _all_ der '.py' oder' .pyc' Datei senden, nur die Quelle der Klasse selbst (wie von http://docs.python.org/library/inspect identifiziert) .html? # inspect.getsource) oder seine 'compile'd Form. –

1

Die Dokumentation erklärt ziemlich gut, was und warum nicht gebeizt werden kann und was nicht.

http://docs.python.org/library/pickle.html#what-can-be-pickled-and-unpickled

Grundsätzlich, wenn die Klasse oder ein Modul mit Namen importierbar ist, wenn es ungebeizte wird, sollte es funktionieren, es sei denn, Sie ändern Ihre Klassendefinition planen zwischen jetzt und wenn Sie es unpickle. In der Klassendefinition unten werden nur der Klassenname "Test" und der Methodenname "mymethod" markiert. Wenn Sie die Klassendefinition herauspicken, dann ändern Sie die Definition, so dass attr ein anderer Wert ist, und mymethod macht etwas völlig anderes, der Pickle wird die neue Definition übernehmen.

class Test(object): 
    attr = 5 

    def mymethod(self, arg): 
     return arg 
1

Wenn Sie dill verwenden, ermöglicht es Ihnen __main__ zu behandeln, als ob es ein Python-Modul waren (zum größten Teil). Daher können Sie interaktiv definierte Klassen und ähnliches serialisieren. dill auch (standardmäßig) kann die Klassendefinition als Teil der Beize transportieren.

>>> class MyTest(object): 
... def foo(self, x): 
...  return self.x * x 
... x = 4 
... 
>>> f = MyTest() 
>>> import dill 
>>> 
>>> with open('test.pkl', 'wb') as s: 
... dill.dump(f, s) 
... 
>>> 

schließen Sie dann den Interpreter nach unten, und die Datei test.pkl über TCP senden. Auf Ihrem Remote-Computer können Sie jetzt die Klasseninstanz abrufen.

Python 2.7.9 (default, Dec 11 2014, 01:21:43) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import dill 
>>> with open('test.pkl', 'rb') as s: 
... f = dill.load(s) 
... 
>>> f 
<__main__.MyTest object at 0x1069348d0> 
>>> f.x 
4 
>>> f.foo(2) 
8 
>>>    

Aber wie bekommt man die Klassendefinition? Das ist also nicht genau das, was du wolltest. Das Folgende ist jedoch.

>>> class MyTest2(object): 
... def bar(self, x): 
...  return x*x + self.x 
... x = 1 
... 
>>> import dill 
>>> with open('test2.pkl', 'wb') as s: 
... dill.dump(MyTest2, s) 
... 
>>> 

Dann nach dem Senden der Datei ... können Sie die Klassendefinition erhalten.

Python 2.7.9 (default, Dec 11 2014, 01:21:43) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import dill 
>>> with open('test2.pkl', 'rb') as s: 
... MyTest2 = dill.load(s) 
... 
>>> print dill.source.getsource(MyTest2) 
class MyTest2(object): 
    def bar(self, x): 
    return x*x + self.x 
    x = 1 

>>> f = MyTest2() 
>>> f.x 
1 
>>> f.bar(4) 
17 

also innerhalb dill, gibt es dill.source, und das hat Methoden, die sie Abhängigkeiten von Funktionen und Klassen, und zusammen mit der Gurke (zum größten Teil) erkennen können.

>>> def foo(x): 
... return x*x 
... 
>>> class Bar(object): 
... def zap(self, x): 
...  return foo(x) * self.x 
... x = 3 
... 
>>> print dill.source.importable(Bar.zap, source=True) 
def foo(x): 
    return x*x 
def zap(self, x): 
    return foo(x) * self.x 

das ist also nicht „perfekt“ (oder vielleicht auch nicht, was erwartet) ... aber es hat den Code für eine dynamisch erstellte Methode serialisiert werden und es ist Abhängigkeiten. Sie bekommen den Rest der Klasse einfach nicht - aber der Rest der Klasse wird in diesem Fall nicht benötigt.

Wenn Sie alles bekommen wollten, könnten Sie einfach die gesamte Sitzung einlegen.

>>> import dill 
>>> def foo(x): 
... return x*x 
... 
>>> class Blah(object): 
... def bar(self, x): 
...  self.x = (lambda x:foo(x)+self.x)(x) 
... x = 2 
... 
>>> b = Blah() 
>>> b.x 
2 
>>> b.bar(3) 
>>> b.x 
11 
>>> dill.dump_session('foo.pkl') 
>>> 

Dann auf der Remote-Maschine ...

Python 2.7.9 (default, Dec 11 2014, 01:21:43) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import dill 
>>> dill.load_session('foo.pkl') 
>>> b.x 
11 
>>> b.bar(2) 
>>> b.x 
15 
>>> foo(3) 
9 

Schließlich, wenn Sie den Transport werden sollen „done“ für Sie transparent, Sie pathos.pp oder ppft verwenden könnten, die die Möglichkeit bieten, Objekte zu einem zweiten Python-Server zu versenden (auf einem entfernten Rechner) oder Python verarbeiten. Sie verwenden dill unter der Haube, und übergeben Sie einfach den Code über die Leitung.

>>> class More(object): 
... def squared(self, x): 
...  return x*x 
... 
>>> import pathos 
>>> 
>>> p = pathos.pp.ParallelPythonPool(servers=('localhost,1234',)) 
>>> 
>>> m = More() 
>>> p.map(m.squared, range(5)) 
[0, 1, 4, 9, 16] 

Das servers Argument ist optional, und hier verbindet nur auf dem lokalen Rechner auf Port 1234 ... aber wenn Sie den Remote-Computer-Namen und Port verwenden, anstatt (oder auch), werden Sie auf das abfeuern Remote-Maschine - "mühelos".

Get dill, pathos und ppft hier: https://github.com/uqfoundation