2017-01-21 3 views
1

ich folgendes zu tun:serialize/Beize eine Funktion, die in einem String definiert ist

import pickle 
namespace = {} 
exec('def f(x): return x', namespace) 
pickle.dumps(namespace['f']) 

Dies führt jedoch zu dem folgenden Fehler:

--------------------------------------------------------------------------- 
PicklingError        Traceback (most recent call last) 
<ipython-input-102-61493bb3c732> in <module>() 
     2 namespace = {} 
     3 exec('def f(x): return x', namespace) 
----> 4 pickle.dumps(namespace['f']) 

PicklingError: Can't pickle <function f at 0x7f2134171950>: it's not the same object as __main__.f 

Das Problem, das ich will lösen: Ich habe eine Funktion im String-Format und ich muss in der Lage sein, es zu serialisieren (für die Parallelisierung).

+0

Sie sollten erklären, was in Ihrem Code geschieht, die nicht Erwartung treffen wird. Was passiert, wenn dieser Code gerade läuft? Was erwartest du sollte passieren. Was * genau * versuchst du mit deinem Code zu erreichen? Bitte überarbeiten Sie, wie Sie ein solideres [mcve] zusammenstellen können, um Ihre Frage besser zu beantworten. – idjaw

+0

Vielen Dank für Ihren Kommentar, ich habe die Fehlermeldung hinzugefügt. Außerdem denke ich, dass ich mein Problem ziemlich deutlich beschreibe. – johnbaltis

Antwort

1

Ich bin mir nicht sicher, warum die Verwendung den dill Tag in Ihrer Frage verwendet, weil man nur pickle verwendet ... aber wenn Sie wirklich Ihren Code müssen genau sein, wie Sie es geschrieben haben, mit dem einem Vorbehalt, dass Sie ersetzen können pickle mit dill ... es funktioniert:

>>> import dill as pickle 
>>> namespace = {} 
>>> exec('def f(x): return x', namespace) 
>>> _f = pickle.dumps(namespace['f']) 
>>> _f 
'\x80\x02cdill.dill\n_create_function\nq\x00(cdill.dill\n_load_type\nq\x01U\x08CodeTypeq\x02\x85q\x03Rq\x04(K\x01K\x01K\x01KCU\x04|\x00\x00Sq\x05N\x85q\x06)U\x01xq\x07\x85q\x08U\x08<string>q\tU\x01fq\nK\x01U\x00q\x0b))tq\x0cRq\r}q\x0e(U\x0c__builtins__q\x0fc__builtin__\n__dict__\nh\nh\x00(h\rh\x0eh\nNN}q\x10tq\x11Rq\x12uh\nNNh\x10tq\x13R0h\x12.' 
>>> f = pickle.loads(_f) 
>>> f(5) 
5 
>>> 
1

Sie können nur übergeben die aktuellen global Namespace zu exec, dann können Sie die f Salbung:

import pickle 
exec('def f(x): return x', globals()) 
pickle.dumps(f) 

Ob Sie es dann in einer anderen Umgebung laden können, ist eine ganz andere Frage diskutiert here.

1

Ohne globals() folgende Arbeiten auch mit:

import pickle 
namespace = {} 
exec('def f(x): return x', namespace) 
f = namespace['f'] # has to have the same name 
pickle.dumps(f) 

Die von namespace genommen Funktion hat in der Funktion Namensraum unter dem gleichen Namen definiert werden.

Verwandte Themen