1

I'm trying to decompile and recompile a function.

def decompile(f):
    return ast.parse(get_code(f), mode='exec')

def recompile(ast):
    return eval(compile(ast, '', 'exec'))

compile(ast) returns a code object, and I can give that to eval() -- but how can I get the live module object back? eval returns None with exec mode. How do I access the evaluated result?

Bach
  • 6,145
  • 7
  • 36
  • 61
salezica
  • 74,081
  • 25
  • 105
  • 166
  • Are you trying to get a function or a module? What do you want to do with the resulting object? – BrenBarn Mar 03 '14 at 07:39
  • Both are okay. I can just access the function inside the live module object – salezica Mar 03 '14 at 07:55
  • What is `get_code()`? Sounds like it returns a code object, which wouldn't be a valid input for `ast.parse()`. It is unclear what you are trying to achieve. – Sven Marnach Mar 03 '14 at 08:44
  • It's just `''.join(inspect.getsourcelines(f)[0])` – salezica Mar 03 '14 at 08:44
  • Thanks. This still doesn't clear up what you actually want to do. Why is a function that parses the source code of a function to an AST called "decompile"? This has nothing to do with decompiling. Please clarify your use case. – Sven Marnach Mar 03 '14 at 08:56
  • I want to write a function decorator that intercepts the definition, modifies the function's ast, and returns a recompiled version – salezica Mar 03 '14 at 08:57
  • Oh, I hope you are doing this just for fun. Using `getsourcelines()` to get the source code of a function will read from disk. The file might be out of sync by now, it might not exist any more, it might never have existed since you are using a `.pyc` distribution, or someone might already have messed around with your function, so this is very unreliable. Your are probably better off writing an import hook that does the modifications (see [this answer](http://stackoverflow.com/a/7880276/279627) for some pointers). And please, never use this in production code. :) – Sven Marnach Mar 03 '14 at 09:09
  • It's just for fun. Is there a more reliable way of going from live function object to ast? Import hooks introduce an extra layer of indirection i'd rather not have – salezica Mar 03 '14 at 19:00
  • No, it's not possible in general to reconstruct the AST from the information in a function object. The code object (`f.__code__`) only contains the Byte code, which is the compiled version of the AST and does not contain all details that are present in the AST. Even if you could reconstruct the AST of the function itself, this wouldn't help, since in general a function must be compiled in context to resolve external references (closure variables are determined statically, which is only possible when the outer scopes are known). – Sven Marnach Mar 03 '14 at 22:34
  • Some modifications could be done on the Byte code level, which would probably tie you to the CPython implementation. Several people have published recipes for bytecode optimization and the like. I currently don't have any link, but search in ActiveState recipes and the likem you'll certainly find something. Since I don't know what modification you are planning, I can't tell whether that will be possible on the bytecode level. – Sven Marnach Mar 03 '14 at 22:37
  • I see. I will do some research. Thank you for your time – salezica Mar 03 '14 at 22:44

0 Answers0