如何在保留调试的同时从字符串加载 Python 模块?
How do I load a Python module from a string while preserving debug?
我有兴趣加载一个 Python 模块,该模块的源代码嵌入到 C 扩展中。应该可以用 Python 的 importlib
机器做一些事情,比如 importlib.util.spec_from_file_location
这样当你调试时源代码就会出现。我将如何实施 importlib.util.spec_from_string
?
作为快速修复,您可以将其转储到临时模块中,使用 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
下面介绍了如何定义从字符串中获取模块源的加载器,然后创建模块并将其加载到 sys.modules
中。如果模块的源不在文件中,它可能很有用。如果已有文件,则使用 https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly
虽然 inspect.getsource(module)
适用于 importlib.abc.InspectLoader
的子类,只需要定义 get_source
,回溯和 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)
我有兴趣加载一个 Python 模块,该模块的源代码嵌入到 C 扩展中。应该可以用 Python 的 importlib
机器做一些事情,比如 importlib.util.spec_from_file_location
这样当你调试时源代码就会出现。我将如何实施 importlib.util.spec_from_string
?
作为快速修复,您可以将其转储到临时模块中,使用 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
下面介绍了如何定义从字符串中获取模块源的加载器,然后创建模块并将其加载到 sys.modules
中。如果模块的源不在文件中,它可能很有用。如果已有文件,则使用 https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly
虽然 inspect.getsource(module)
适用于 importlib.abc.InspectLoader
的子类,只需要定义 get_source
,回溯和 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)