Skip to content Skip to sidebar Skip to footer

How To Execute Nested Pycode Objects

Let's say we have a code object like this: code = ''' x = 'unrelated' y = dangerous_function() def foo(): return 'say foo' ''' code_obj = compile(code, '', 'exec

Solution 1:

The co_const attribute holds just the constant literals defined in a code object, so in your example it holds just the code that loads 'say foo' as an argument for return, which can be verified with dis:

import dis
for obj in code_obj.co_consts:
    if isinstance(obj, types.CodeType):
        dis.dis(obj)

This outputs:

  5           0 LOAD_CONST               1 ('say foo')
              2 RETURN_VALUE

So by executing this code object it naturally would not define any names.

If you would like to execute just a specific function in a given source code, you can parse the code with ast.parse and use a ast.NodeVisitor subclass to extract the function node, wrap it with a Module node so you can compile and execute it alone:

import ast

classget_function(ast.NodeVisitor):
    def__init__(self, name):
        self.name = name
        self.code = Nonedefvisit_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'))

This outputs:

<function foo at 0x018735D0>

EDIT: Alternatively and more simply, you can use the ast.walk function to traverse the nodes with a for loop:

import ast

for node in ast.walk(ast.parse(code, '<string>')):
    ifisinstance(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'))

Post a Comment for "How To Execute Nested Pycode Objects"