Я экспериментировал с AST в python. Я хочу изменить методы путем преобразования AST во время выполнения.
Я могу получить источник предварительно скомпилированного метода, используя inspect.getsource()
, и
Я могу изменить AST по мере необходимости, используя посетителей AST.
Это, вероятно, довольно наивно, но я бы хотел иметь возможность скомпилировать AST и сделать что-то похожее на:
myClass.method.__func__.__code__ = compile(newAST, '<string>', 'exec')
Но компиляция будет принимать только AST с модулем ast.Module в качестве пользователя root.
Есть ли способ либо скомпилировать просто ast.FunctionDef, либо получить объект кода функции из скомпилированного (и в противном случае пустого) кода модуля?
Буду признателен за любые указатели на информацию, охватывающую подобные вещи. Примеры AST, которые я видел, имеют дело только с простыми выражениями.
Я понял, что мне нужно просто выполнить модуль в пространстве имен, и тогда я получу доступ к нормальной структуре.
Итак, картина такова:
src = inspect.getsource(myClass.myMethod)
astFromSrc = ast.parse(unindent(src)) # need to remove extra indent from method
transform(astFromSrc.body) # transform the AST as you need
ast.fix_missing_locations(astFromSrc) # fix up line numbers etc
compiled = compile(astFromSrc, '<string>', 'exec') # compile the module AST
####### From here is the part I was missing
myScope = {} # make an empty namespace
exec compiled in myScope # now myScope contains a proper compiled function
# Now replace the original with the modified version
myClass.myMethod.__func__.__code__ = myScope['myMethod'].__code__
Но теперь у меня есть еще один вопрос:
Как вставить это в обычный процесс сборки Python, чтобы изменения выполнялись только один раз, а затем загружаться из файла .pyc?