How to execute nested PyCode objects
假设我们有这样的代码对象:
1 2 3 4 5 6 7 8  | code = ''' x = 'unrelated' y = dangerous_function() def foo(): return 'say foo' ''' code_obj = compile(code, '<string>', 'exec')  | 
我不想只执行它,因为谁知道会发生什么(特别是
1 2 3 4 5 6 7 8 9 10 11 12  | import types     new_objects = [] for obj in code_obj.co_consts: if isinstance(obj, types.CodeType): new_objects.append(obj.co_name) print(obj) #"<code object foo at 0x7f4e255d3150, file"<string>", line 4>" # ... looks promising, so let's exec it! exec(obj) print(new_objects[0]) #"foo" print(eval(new_objects[0])) #"NameError: name 'foo' is not defined"  | 
我本以为最后一份声明是打印
有办法吗?
1 2 3 4  | import dis for obj in code_obj.co_consts: if isinstance(obj, types.CodeType): dis.dis(obj)  | 
此输出:
1 2  |   5           0 LOAD_CONST               1 ('say foo') 2 RETURN_VALUE  | 
因此,通过执行这个代码对象,它自然不会定义任何名称。
如果您只想在给定的源代码中执行一个特定的函数,您可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15  | import ast class get_function(ast.NodeVisitor): def __init__(self, name): self.name = name self.code = None def visit_FunctionDef(self, node): if node.name == self.name: self.code = compile(ast.fix_missing_locations(ast.Module(body=[node])), '<string>', 'exec') func = get_function('foo') func.visit(ast.parse(code, '<string>')) exec(func.code) print(eval('foo'))  | 
此输出:
1  | <function foo at 0x018735D0>  | 
编辑:或者更简单地说,您可以使用
1 2 3 4 5 6 7 8  | import ast for node in ast.walk(ast.parse(code, '<string>')): if isinstance(node, ast.FunctionDef) and node.name == 'foo': code_obj = compile(ast.fix_missing_locations(ast.Module(body=[node])), '<string>', 'exec') exec(code_obj) print(eval('foo'))  |