Сериализация / выборка функции, определенной в строке

Я хочу сделать следующее:

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

Однако это приводит к следующей ошибке:

---------------------------------------------------------------------------
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

Проблема, которую я хочу решить: у меня есть функция в строковом формате, и мне нужно иметь возможность ее сериализации (для целей распараллеливания).

3 ответа

Решение

Я не уверен, почему использовать использовали dill тег в вашем вопросе, потому что вы использовали только pickle... но если вам действительно нужно, чтобы ваш код был точно таким, каким вы его написали, с одним предупреждением, которое вы можете заменить pickle с dill... оно работает:

>>> 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
>>> 

Вы можете просто передать ток global Пространство имен для exec, тогда вы можете выбрать функцию:

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

Можете ли вы затем загрузить его в другой среде, это совершенно другой вопрос, который обсуждается здесь.

Без использования globals() следующие работы также:

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

Функция взята из namespace должен быть определен в пространстве имен функции под тем же именем.

Другие вопросы по тегам