Как вы получаете Python для записи кода функции, имеющейся в памяти?

Когда я передаю параметры в программе (эксперимент по вычислительной биологии), я обычно передаю их через .py-файл.
Поэтому у меня есть этот .py-файл, который читается так:

starting_length=9 starting_cell_size=1000 LengthofExperiments=5000000 

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

 def writeoptions(directory): options="" options+="starting_length=%s%s"%(starting_length,os.linesep) options+="starting_cell_size=%s%s"%(starting_cell_size,os.linesep) options+="LengthofExperiments=%s%s"%(LengthofExperiments,os.linesep) ... open("%s%soptions.py"%(directory,os.sep),'w').write(options) 

Я хочу передать функцию в качестве одного из параметров:

 starting_length=9 starting_cell_size=1000 LengthofExperiments=5000000 def pippo(a,b): return a+b functionoperator=pippo 

И, конечно же, в реальном эксперименте функция pippo будет намного сложнее. И отличается от эксперимента к эксперименту.

Но то, что я не могу сделать, – это написать функцию автоматически. Короче говоря, я не знаю, как обобщить функцию writeoptions, чтобы продолжать писать параметры, если один из вариантов – это функция. Я мог бы, конечно, скопировать исходный файл, но это неэффективно, неэффективно (потому что в нем содержится много дополнительных опций, которые не используются), и, как правило, не решает вопрос.

Как заставить python записывать код функции, поскольку он записывает значение переменной?

5 Solutions collect form web for “Как вы получаете Python для записи кода функции, имеющейся в памяти?”

 vinko @ mithril $ больше a.py

 def foo (a):
   распечатать

 vinko @ mithril $ more b.py

 импортировать
 проверка импорта

 a.foo (89)
 print inspect.getsource (a.foo)

 vinko @ mithril $ python b.py
 89
 def foo (a):
   распечатать

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

 alias run_py='svn ci -m "Commit before running"; python2.5 $*' 

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

Другим, существенно менее полнофункциональным средством отслеживания ввода функции может быть нечто вроде LodgeIt , пастебина , который принимает вход XML-RPC и поставляется с привязками Python. (Он может быть установлен локально и имеет поддержку для ответа и обновления существующих паст.)

Но, если вы ищете относительно небольшой объем кода, который должен быть включен, решение Vinko, использующее проверку, должно работать достаточно хорошо. Дуг Хеллман рассмотрел модуль inspect в своем модуле Python Module of the Week . Вы можете создать декоратор, который проверяет каждую опцию и аргумент, а затем распечатывает его соответствующим образом (я буду использовать inspect.getargspec для получения имен аргументов.)

 import inspect from functools import wraps def option_printer(func): @wraps(func) def run_func(*args, **kwargs): for name, arg in zip(inspect.getargspec(func)[0], args) \ + sorted(kwargs.items()): if isinstance(arg, types.FunctionType): print "Function argument '%s' named '%s':\n" % (name, func.func_name) print inspect.getsource(func) else: print "%s: %s" % (name, arg) return func(*args, **kwargs) return run_func 

Вероятно, это можно сделать немного более изящным, но в моих тестах он работает для простых наборов аргументов и переменных. Кроме того, у него могут быть проблемы с лямбдами.

Вы спрашиваете об этом?

 def writeoptions(directory): options="" options+="starting_length=%s%s"%(starting_length,os.linesep) options+="starting_cell_size=%s%s"%(starting_cell_size,os.linesep) options+="LengthofExperiments=%s%s"%(LengthofExperiments,os.linesep) options+="def pippo(a,b):%s" % ( os.linesep, ) options+=" '''Some version of pippo'''%s" % ( os.linesep, ) options+=" return 2*a+b%s" % ( os.linesep, ) open("%s%soptions.py"%(directory,os.sep),'w').write(options) 

Или что-то другое?

Хотя можно делать то, что вы просите (как показал Винько), я бы сказал, что использовать код проще. Положите pippo и его приятелей в подмодуль, доступ к которым обе программы могут получить.

Вместо того, чтобы погружаться в тему дизассемблеров и байт-кодов (например, проверять ), почему бы вам просто не сохранить созданный источник Python в модуле ( file.py ), а затем импортировать его?

Я бы предложил изучить более стандартный способ обработки того, что вы называете опциями . Например, вы можете использовать модуль JSON и сохранять или восстанавливать свои данные. Или загляните в модули маршала и рассола .

Python - лучший язык программирования в мире.