Как сериализовать симпатическую функцию?
Название говорит само за себя. Есть ли способ сериализовать функцию, генерируемую sympy?лямбдифь?:
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
... Причина, по которой я хочу это сделать, заключается в том, что мой код генерирует так много лямбдифицированных функций, но я обнаружил, что это занимает слишком много времени каждый раз.
2 ответа:
Вы на самом деле можете использовать
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
, так что я бы знал.
Действительно-рассол, капуста и даже укроп терпят неудачу на этом примере с настройками по умолчанию.
, но 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