TomCho
TomCho

Reputation: 3507

python - How to inspect code of function created with exec

I have a function that was created with exec() inside another function and passed as an argument to the main program. How can I get the code of said function? I tried inspec.getsourcelines() and inspec.getsource() but I get the following error

IOError: could not get source code

Is there a way around this?

MWE main file:

#!/usr/bin/python
from ext import makeF
import inspect

f=makeF()
f()
inspect.getsource(f)

then external file:

def makeF():
    script="def sayA():\n\tprint('Aah')"
    exec(script)
    return sayA

Upvotes: 4

Views: 1384

Answers (2)

Serge Ballesta
Serge Ballesta

Reputation: 148880

In python 3 the solution is the __globals__ attribute of the functions.

With your example :

>>> f.__globals__['txt']
"def sayA():\n\tprint('Aah')"

Unfortunately I could not find anything like for Python 2.


The reason why the other methods cannot work, is because they use the filename of the module and here you do not have any file.

Upvotes: 1

wonderb0lt
wonderb0lt

Reputation: 2043

This is not possible. I've been digging around and came to the same conclusion as outlined in this answer.

I don't know your code, but I think in your specific case you could return a custom object containing the source code of the function (which you seem to have - you're passing it to exec) together with the actual compiled function. You could even leverage Python's __call__ magic method to better emulate the original behaviour. Here's a sample:

class FunctionWithCode:
    def __init__(self, source, func_name):
        exec(source)
        self.source = source
        self.func = locals()[func_name]

    def __call__(self, *args, **kwargs):
        self.func(*args, **kwargs)

f = FunctionWithCode("def sayA():\n\tprint('Aah')", 'sayA')

f()

which prints Aah as expected. You would need to know the function name when creating the object but this is the same for your sample code.

Upvotes: 2

Related Questions