pythonpython-importlibdynamic-importpython-inspect

Using inspect.getsourcelines() for a module that is not stored in the same folder


I have a module stored in some specific local location on which I am performing dynamic import using, importlib in python. After importing the module I am using file.readlines() to read all the lines in the file. If the file has a function called foo I want to get the source code of the function.

The program I am using, I have written below. When I use this program, I am getting error NameError: name 'file_name' is not defined

Note: I have separated file name from the location and hence I have written the file_name directly as a variable below.

spec = importlib.util.spec_from_file_location(file_name, file_location)
load_module = importlib.util.module_from_spec(spec)

with open(file_abs_location, "r") as file:
    lines = file.readlines()
    for line in lines:
        if line.startswith("def foo"):
            line = line.replace("def ", "").replace("():", "")
            _name = file_name.replace("py", "")
            final_string = _name+line
            print(final_string)
            function_lines = inspect.getsourcelines(eval(final_string))

And I know that I am already reading the lines of the file and I can get function content from there but the problem is that I have to run this for many files and each file has different number of rows in foo function. So I cannot read a definite amount of lines after a function name.

Considering all my constraints, can someone please guide me on how to do this?


Solution

  • I'm not 100% sure what your aim is but I think you are making it a bit more complicated than it needs to be. You can use getattr on the module to find out if that function exists and if it does then get the function lines.

    Here is an example to get the lines of the merge function in pandas (the superfulous use of importlib is just to more closely match the question above)

    import importlib, inspect
    load_module = importlib.import_module("pandas")
    if func := getattr(load_module, "merge", None):
        function_lines = inspect.getsourcelines(func)