How can I dynamically execute function in current scope and add it as property of the calling function?

≡放荡痞女 提交于 2020-01-25 11:06:22

问题


I have some code like this:

def f1():
  <some stuff here>
.
.
.

@mylib.codegen
def f2(args):
  f1()
  <some more stuff here>

mylib.py :

def codegen(fn):
  src = inspect.getsource(fn)
  original_ast = ast.parse(src)
  new_ast = transform_ast(original_ast)
  code_obj = compile(new_ast, '<auto-generated>', 'exec')
  myscope = {}
  exec code_obj in myscope
  fn.generated_fn = myscope['name']   # Where name is the binding created by execing code_obj

To summarize, mylib.codegen is a decorator which parses code of f, creates an ast of another function based on ast of f, execs code of generated function to get a callable function and sets callable function as a property of f. That means when f2 is imported the first time, f2 dynamically gets another function as property of itself.

Generated function also needs to call f1 but it can't find f1 in myscope. If somehow Python allowed inlining, and I had inlined code of mylib.codegen, everything would have been fine but I don't think Python allows inlining of code. How do I set things up so that generated code object is execed in namespace of caller function?


回答1:


The fn.func_globals contains the global namespace for a given function; you'll need it to be able to exec the transformed and recompiled code object:

myscope = {}
myscope.update(fn.func_globals)

Do not use fn.func_globals directly; you wouldn't want to overwrite items in that namespace.



来源:https://stackoverflow.com/questions/13849960/how-can-i-dynamically-execute-function-in-current-scope-and-add-it-as-property-o

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!