Как замариновать функцию Python с ее зависимостями?

В качестве продолжения этого вопроса: Есть ли простой способ замариновать функцию Python (или иным образом сериализовать ее код)?

Я хотел бы увидеть пример этой пули из сообщения выше:

«Если функция ссылается на глобальные переменные (включая импортированные модули, другие функции и т. д.), которые вам нужно подобрать, вам нужно будет сериализовать эти тоже или воссоздать их на удаленной стороне. В моем примере просто указано глобальное пространство имен удаленного процесса».

У меня есть простой тест, в котором я пишу байтовый код функции в файл, используя marshal:

def g(self,blah): 
    print blah

def f(self):
    for i in range(1,5):
        print 'some function f'
        g('some string used by g')

data = marshal.dumps(f.func_code)

file = open('/tmp/f2.txt', 'w')
file.write(data)

Затем запускаю новый экземпляр Python, который я делаю:

file = open('/tmp/f2.txt', 'r')
code = marshal.loads(file.read())
func2 = types.FunctionType(code, globals(), "some_func_name");
func2('blah')

В результате получается:

NameError: global name 'g' is not defined

Это не зависит от различные подходы, которые я сделал для включения g. Я пробовал в основном тот же подход к отправке g как f, но f все еще не может видеть g. Как поместить g в глобальное пространство имен, чтобы его мог использовать f в процессе получения?

Кто-то также порекомендовал взглянуть на пиротехнику как на пример того, как это сделать. Я уже пытался понять соответствующий код в проекте disco. Я взял их класс dPickle и безуспешно попытался воссоздать их функциональность disco/tests/test_pickle.py в отдельном приложении. В моем эксперименте были проблемы с маршалингом функций с вызовом дампов. В любом случае, возможно, следующим будет пироразведка.

Подводя итог, можно сказать, что основная функциональность, которую я ищу, — это возможность отправить метод по сети и получить вместе с ним все основные методы «рабочей области» (например, g).

Пример с изменениями из ответа:

Работающая функция_сочинитель:

import marshal, types

def g(blah): 
    print blah


def f():
    for i in range(1,5):
        print 'some function f'
        g('blah string used by g')


f_data = marshal.dumps(f.func_code)
g_data = marshal.dumps(g.func_code);

f_file = open('/tmp/f.txt', 'w')
f_file.write(f_data)

g_file = open('/tmp/g.txt', 'w')
g_file.write(g_data)

Работающая функция_считыватель:

import marshal, types

f_file = open('/tmp/f.txt', 'r')
g_file = open('/tmp/g.txt', 'r')

f_code = marshal.loads(f_file.read())
g_code = marshal.loads(g_file.read())

f = types.FunctionType(f_code, globals(), 'f');
g = types.FunctionType(g_code, globals(), 'g');

f()

15
задан Community 23 May 2017 в 12:32
поделиться