importlib._bootstrap 和 python 解释器初始化

KOL*_*ICH 6 python cpython initialization python-3.x

CPython 解释器模块导入系统是用 python 本身编写的,并在importlib._bootstrap. 它的源代码可以在 中看到importlib/_bootstrap.py,但它不是从那里加载的。相反,它是从所谓的冻结模块加载的,该模块的字节码被烘焙到解释器库(python37.dll)中。

解释器通过导入(它是烘焙到解释器中_frozen_importlib的名称importlib._bootstrap)和调用_install在那里定义的函数来初始化自身,并将sys_imp模块作为参数传递_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
    ...
Run Code Online (Sandbox Code Playgroud)

不幸的是,发生了一些奇怪的事情,调用 io.open 导致_install退出,控制流永远不会到达下一条语句。并且似乎没有引发异常,当出现异常时,解释器会打印它,而是由于缺少 的副作用而在另一个地方引发异常_install

然而另一个麻烦是它sys.stdout没有初始化,所以我们不能print而且必须依赖异常来调试输出。

所以

  1. 我该怎么做open工作?

  2. 我应该如何初始化sys.stdout

KOL*_*ICH 0

不完全是一个答案,但我只为我的案例解决了一个问题(加载 python 源代码)。

我该怎么做open工作?

结果当时字符串编码不可用,所以我rbr. 然后我将 传递给bytescompile它可以处理它们。