2015-07-09 9 views
6

Der Titel sagt alles. Gibt es eine Möglichkeit, eine Funktion zur Serialisierung von sympy.lambdify erzeugt ?:Wie zu sympy lambified Funktion serialisieren?

import sympy as sym 
import pickle 
import dill 
a, b = sym.symbols("a, b") 
expr = sym.sin(a) + sym.cos(b) 
lambdified_expr = sym.lambdify((a, b), expr, modules="numpy") 
pickle.dumps(lambdified_expr) # won't work 
dill.dumps(lambdified_expr) # won't work either 

... Der Grund, warum ich dies tun wollen ist, weil mein Code so viele lambdified Funktionen erzeugt, aber ich fand es jedes Mal zu lange dauert .

Antwort

4

Sie tatsächlich können Verwendung dill es beizen. Die neuesten Versionen von dill (z. B. auf github) haben "Einstellungen", die Varianten der Konstruktion des Beizgeräts unter dump ermöglichen. Ja, die Standardeinstellungen für dill schlagen für dieses Objekt fehl, aber nicht, wenn Sie die Einstellung verwenden, die globale Referenzen rekursiv verfolgt (z. B. recurse = True). Diese Einstellung entspricht der Einstellung cloudpickle.

>>> import sympy as sym 
>>> import pickle 
>>> import dill 
>>> a, b = symbols("a, b") 
>>> a, b = sym.symbols("a, b") 
>>> expr = sym.sin(a) + sym.cos(b) 
>>> lambdified_expr = sym.lambdify((a, b), expr, modules="numpy") 
>>> 
>>> dill.settings 
{'recurse': False, 'byref': False, 'protocol': 2, 'fmode': 0} 
>>> dill.settings['recurse'] = True 
>>> dill.dumps(lambdified_expr) 
'\x80\x02cdill.dill\n_create_function\nq\x00(cdill.dill\n_unmarshal\nq\x01U\x83c\x02\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00C \x00\x00s\x14\x00\x00\x00t\x00\x00|\x00\x00\x83\x01\x00t\x01\x00|\x01\x00\x83\x01\x00\x17S(\x01\x00\x00\x00N(\x02\x00\x00\x00t\x03\x00\x00\x00sint\x03\x00\x00\x00cos(\x02\x00\x00\x00t\x01\x00\x00\x00at\x01\x00\x00\x00b(\x00\x00\x00\x00(\x00\x00\x00\x00s\x08\x00\x00\x00<string>t\x08\x00\x00\x00<lambda>\x01\x00\x00\x00s\x00\x00\x00\x00q\x02\x85q\x03Rq\x04}q\x05(U\x03cosq\x06cnumpy.core.umath\ncos\nq\x07U\x03sinq\x08cnumpy.core.umath\nsin\nq\tuU\x08<lambda>q\nNN}q\x0btq\x0cRq\r.' 

P.S. Ich bin der Autor dill, also würde ich wissen.

+0

Warum ist Recurse = True keine Standardoption? – denfromufa

+1

Da 'Dill' eine breite Palette von Objekten serialisieren kann, bietet 'recurse = False' die größte Abdeckung. Wenn Sie 'recurse = True 'verwenden, funktioniert es für bestimmte Objekte sehr gut, bricht jedoch die Serialisierung für eine Reihe von Fällen. Wenn (oder wann) ich die Fälle auflöse, die es unterbricht, wird es zum Standard werden. Bis dahin ist es am besten, die Standardfunktionalität * nicht * zu entfernen, sondern neue Funktionen über eine Einstellung bereitzustellen. Siehe: https://github.com/uqfoundation/dill/issues/105 –

+0

@MikeMcKerns Ich habe eine Einschränkung, für ziemlich große lambadified Funktionen bekomme ich 'RuntimeError: maximale Rekursion Tiefe überschritten beim Aufruf eines Python-Objekts'. –

2

In der Tat - Pickle, cPickle und sogar Dill in diesem Beispiel mit Standardeinstellungen fehlschlagen.

Aber Cloudpickle versagt nicht!

pip install cloudpickle 

oder

https://github.com/cloudpipe/cloudpickle

import sympy as sym 
from cloudpickle import dumps, loads 
a, b = sym.symbols("a, b") 
expr = sym.sin(a) + sym.cos(b) 
lambdified_expr = sym.lambdify((a, b), expr, modules="numpy") 
var=dumps(lambdified_expr) 
a1=lambdified_expr(10,10) 
del lambdified_expr 
lambdified_expr=loads(var) 
a2=lambdified_expr(10,10) 
a1==a2 # True