Как сериализовать симпатическую функцию?


Название говорит само за себя. Есть ли способ сериализовать функцию, генерируемую 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 7

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