2015-07-09 2 views
6

Название говорит все. Есть ли способ, чтобы сериализовать функцию, порожденную sympy.lambdify ?:Как сериализовать функцию sympy lambdified?

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 

... Поэтому я хочу сделать это, потому что мой код генерирует столько lambdified функций, но я нашел, что это занимает слишком много времени каждый раз, когда ,

ответ

4

Вы на самом деле может использовать dill замариновать его. В последних версиях dill (например, на github) есть «настройки», которые позволяют варианты построения рассола на dump. Да, настройки по умолчанию для dill сбой на этом объекте, но нет, если вы используете параметр, который рекурсивно отслеживает глобальные ссылки (т. Е. recurse = True). Эта настройка похожа на то, что по умолчанию дает 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. Я автор dill, так что я знаю.

+0

Почему recurse = True не является вариантом по умолчанию? – denfromufa

+1

Поскольку 'dill' может сериализовать широкий диапазон объектов, а' recurse = False' обеспечивает самый широкий диапазон охвата. Если вы используете 'recurse = True', он отлично работает для определенных объектов, но прерывает сериализацию для ряда случаев. Если (или когда) я разрешаю случаи, которые он ломает, тогда он станет стандартным. До тех пор наилучшим выбором является * не * удаление функций по умолчанию, но предоставление новых функций с помощью настройки. См .: https://github.com/uqfoundation/dill/issues/105 –

+0

@MikeMcKerns У меня есть одно предостережение, поскольку для достаточно больших lambadified функций я получаю 'RuntimeError: максимальная глубина рекурсии превышена при вызове объекта Python'. –

2

Действительно - pickle, cPickle и даже укроп в этом примере с настройками по умолчанию.

Но cloudpickle не подведет!

pip install cloudpickle 

или

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 
Смежные вопросы