Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I load a Python module from a string while preserving debug?

I'm interested in loading a Python module that has its source embedded in a C extension. It should be possible to do something with Python's importlib machinery like importlib.util.spec_from_file_location so that the source code will appear if you are debugging. How would I implement an importlib.util.spec_from_string?

like image 214
joeforker Avatar asked Dec 10 '25 17:12

joeforker


2 Answers

Here's how to define a loader that takes the module's source from a string, and then creates and loads the module into sys.modules. It could be useful if the module's source is not in a file. If there is already a file then use https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly

Although inspect.getsource(module) works for a subclass of importlib.abc.InspectLoader for which it would only be necessary to define get_source, tracebacks and pdb don't appear to be willing to display the source code until you inherit from SourceLoader.

import sys
import importlib.abc, importlib.util

class StringLoader(importlib.abc.SourceLoader):
    def __init__(self, data):
        self.data = data

    def get_source(self, fullname):
        return self.data
    
    def get_data(self, path):
        return self.data.encode("utf-8")
    
    def get_filename(self, fullname):
        return "<not a real path>/" + fullname + ".py"
    
module_name = "testmodule"
with open("testmodule.py", "r") as module:
    loader = StringLoader(module.read())

spec = importlib.util.spec_from_loader(module_name, loader, origin="built-in")
module = importlib.util.module_from_spec(spec)
sys.modules[module_name] = module
spec.loader.exec_module(module)
like image 114
joeforker Avatar answered Dec 13 '25 07:12

joeforker


As a quick fix, you can dump it in a temporary module, import it using exec and delete the temp module when you're done.

Here's a toy example:

dummy_src =""" 
print("imported!") 
x = 5 
""" 

with open("temp.py", "w") as f: 
    f.write(dummy_src) 

exec("import temp") 
print(temp.x)

Output:

imported!
5
like image 30
altugkarakurt Avatar answered Dec 13 '25 07:12

altugkarakurt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!