importlib._bootstrap и инициализация интерпретатора Python - PullRequest
0 голосов
/ 16 января 2019

Система импорта модулей интерпретатора 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 и вынуждены полагаться на исключения для вывода отладки.

So

  1. Как мне заставить open работать?

  2. Как мне инициализировать sys.stdout?

1 Ответ

0 голосов
/ 06 февраля 2019

Не совсем ответ, но я решил одну проблему только для моего случая (загрузка исходного кода Python).

Как мне заставить open работать?

Оказалось, что в это время строковые кодировки недоступны, поэтому я использовал rb вместо r. Затем я передаю bytes на compile, он может справиться с ними.

...