简体   繁体   中英

How to get source inside exec python

I currently have the problem that I cant use inspect.getsource (OSError: could not get source code) inside code executed through exec() .

For example when i feed the following code as a string into exec(code)

import inspect

def sample(p1):
    print(p1)
    return 1

print(inspect.getsource(sample))

So does anyone know how i could get the source inside the exec() ?

I use python 3.8 64 Bit

Thank you for your answers.

Edit : First of all, thanks for the answers and the help to get the right formating for my question, but the function and the inspect.getsource() have to be inside the exec() string.

Regrettably, as I'm sure you've realised, this simply is not possible using exec ...but it is possible using exec_module .

If you are not required to use exec specifically, this may work for you:

import tempfile
from importlib import util
import importlib.machinery

raw = """
def sample(p1):
    print(p1)
    return 1

import inspect
print(inspect.getsource(sample))
"""

# Create a temporary source code file
with tempfile.NamedTemporaryFile(suffix='.py') as tmp:
    tmp.write(raw.encode())
    tmp.flush()

    # Now load that file as a module
    spec = util.spec_from_file_location('tmp', tmp.name)
    module = util.module_from_spec(spec)
    spec.loader.exec_module(module)

    # ...or, while the tmp file exists, you can query it externally
    import inspect
    print(inspect.getsource(module.sample))

The TLDR is, without a source file, it is just flat out not-possible to use getsource to read the source code of a function, because the implementation reads the source code from the file defined in f.__code__.co_filename on the function (read-only, so monkey patching is impossible).

However, if you write the source code to a temporary file, you can load that file as a module ( exec_module is practically identical to the effect of exec , you just have to do a few other steps first).

Note: tmp.flush() <-- don't forget this, tmp.write() doesn't write until you flush, and you'll be 'loading' an empty file if you don't flush it first.

If your code is like this:

exec("""\
import inspect

def sample(p1):
    print(p1)
    return 1

print(inspect.getsource(sample))\
""")

And the exception is OSError: could not get source code then that probably means that inspect.getsource() requires a file's source to inspect. exec is a dynamic execution of python code so the sample function that's being defined from exec is not on the file's source!

Something like this:

def sample(p1):
    print(p1)
    return 1

exec("""\
import inspect
print(inspect.getsource(sample))\
""")

would work because the function sample is defined in the source!

Hope that makes sense and answers your question!

~ PanTrakX

I currently have the problem that I cant use inspect.getsource (OSError: could not get source code) inside code executed through exec() .

For example when i feed the following code as a string into exec(code)

import inspect

def sample(p1):
    print(p1)
    return 1

print(inspect.getsource(sample))

So does anyone know how i could get the source inside the exec() ?

I use python 3.8 64 Bit

Thank you for your answers.

Edit : First of all, thanks for the answers and the help to get the right formating for my question, but the function and the inspect.getsource() have to be inside the exec() string.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM