importlib._bootstrap и инициализация интерпретатора Python
Система импорта модулей интерпретатора 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
...
К сожалению, происходит что-то странное, и вызов io.open вызывает _install
чтобы выйти, поток управления никогда не достигает следующего оператора. И никакое исключение не возникает, когда интерпретатор печатает его, вместо этого возникает исключение в другом месте из-за отсутствия побочного эффекта _install
,
Еще одна неприятность заключается в том, что sys.stdout
не инициализируется, поэтому мы не можем print
и должны полагаться на исключения для вывода отладки.
Так
Как я должен сделать
open
Работа?Как я должен инициализировать
sys.stdout
?
1 ответ
Не совсем ответ, но я решил одну проблему только для моего случая (загрузка исходного кода Python).
Как я должен сделать
open
Работа?
Оказалось, что строковое кодирование недоступно в то время, поэтому я использовал rb
вместо r
, Тогда я передаю bytes
в compile
С ними можно иметь дело.