如何在保留调试的同时从字符串加载Python模块?

2024-04-18 12:11:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我感兴趣的是加载一个源代码嵌入到C扩展中的Python模块。应该可以使用Python的importlib机制(如importlib.util.spec_from_file_location)执行某些操作,以便在调试时显示源代码。我将如何实现importlib.util.spec_from_string


Tags: 模块fromstring源代码utillocationimportlib感兴趣
2条回答

下面是如何定义从字符串获取模块源代码的加载程序,然后创建模块并将其加载到sys.modules。如果模块的源代码不在文件中,那么它可能很有用。如果已经有文件,则使用https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly

尽管inspect.getsource(module)适用于只需要定义get_sourceimportlib.abc.InspectLoader子类,但回溯和pdb似乎不愿意显示源代码,直到您从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_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)

作为快速修复,您可以将其转储到临时模块中,使用exec导入它,并在完成后删除临时模块

下面是一个玩具示例:

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

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

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

输出:

imported!
5

相关问题 更多 >