【发布时间】:2019-02-06 14:13:36
【问题描述】:
CPython解释器模块导入系统是用python本身编写的,并在importlib._bootstrap中初始化。它的来源可以在importlib/_bootstrap.py 中看到,但它不是从那里加载的。相反,它是从所谓的冻结模块中加载的,该模块的字节码是baked 到解释器库(python37.dll)中。
解释器通过importing _frozen_importlib (it's a name for importlib._bootstrap baked into the interpreter) 和calling _install function defined there, passing sys and _imp modules as arguments 初始化自己。 _install 调用 _setup,初始化此模块所需的运行时,然后添加 2 个导入器,实现 PEP 451。
在开发自定义导入器时,我在_bootstrap.py 或我的导入器中遇到了几个错误,因此我需要在_bootstrap.py 中添加一些调试输出。
所以我尝试让解释器从磁盘加载_bootstrap.py,而不是从烘焙的字节码中加载。
对 cpython 源代码的分析表明,为了导入内置模块,我不需要大部分 spec 类。所以内置模块可以使用_create_builtin导入
class UltraSimpleSpec:
__slots__=("name",)
def __init__(self, name):
self.name = name
def _install(sys, _imp):
io = _imp.create_builtin(UltraSimpleSpec("_io"))
_bi = _imp.create_builtin(UltraSimpleSpec("builtins"))
fd = io.open("path/to/_bootstrap.py", "rt") # exits the _install function without any exception, how can it do it?
raise _bi.Exception("Never called") # _bi.print doesn't work, because sys.stdout is not initialized, so I have to use exceptions for debug output
...
不幸的是,发生了一些奇怪的事情,调用 io.open 导致_install 退出,控制流永远不会到达下一条语句。而且似乎没有引发异常,当它出现时,解释器会打印它,而是由于缺少_install 的副作用而在另一个地方引发异常。
还有一个麻烦是sys.stdout 没有初始化,所以我们不能print 并且不得不依赖异常来调试输出。
所以
我应该如何让
open工作?我应该如何初始化
sys.stdout?
【问题讨论】:
-
我很想知道你在“_bootstrap.py”中遇到的那些错误,即使在像wasm或android这样奇怪的平台上也不需要修改它。你想达到什么目标?
-
IDK 暂时(尚未调试它,很忙),但在与我的自定义模块加载器交互时它会中断。 1
importlib.reload不起作用。 2.当我用my custom loader, wrappingimportlib.import_module加载一个模块时,当我稍后加载该模块的一个子模块时,我得到一个模块不存在的错误。 -
您可能需要在使用重载或插件系统之前调用 importlib.invalidate_caches()。
标签: python python-3.x initialization cpython