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 源代码的分析表明,为了导入内置模块,我不需要大部分的规范类。因此可以使用 _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 未初始化,因此我们无法打印
并且必须依赖异常来进行调试输出。
所以
我应该如何使
open
工作?我应该如何初始化
sys.stdout
?
最佳答案
不完全是一个答案,但我只为我的案例解决了一个问题(加载 python 源代码)。
How should I make
open
work?
结果当时字符串编码不可用,所以我用了rb
而不是r
。然后我将字节
传递给compile
,它可以处理它们。
关于python - importlib._bootstrap 和 python 解释器初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54224735/