Как устроен CPython? Что такое bytecode, dis, compile()?

CPython — это реализация Python на C с классическим байткод‑интерпретатором: исходник сначала парсится в AST, затем компилируется в байткод, который исполняет виртуальная машина; модуль dis позволяет дизассемблировать байткод, а встроенная функция compile() даёт доступ к шагу компиляции из кода.
Подробный ответ

На уровне senior полезно показать, что вы понимаете хотя бы верхнеуровневую архитектуру CPython и умеете использовать инструменты, которые она предоставляет.

Кратко об архитектуре CPython

  • реализация интерпретатора и стандартной библиотеки написана на C;

  • исходный код Python‑модулей проходит через этапы: парсинг → AST → байткод → исполнение стековой виртуальной машиной;

  • объекты (числа, строки, списки, классы и т.п.) — структуры на C, живущие в куче и управляемые подсчётом ссылок + GC для циклов;

  • GIL синхронизирует доступ потоков к этим объектам.

Что такое байткод

Байткод — это последовательность инструкций, которую исполняет виртуальная машина CPython (stack‑based VM). При первом импорте модуля код компилируется в объект code, который содержит байткод, константы, список переменных и т.д., и может кешироваться в __pycache__.

def add(a, b):
   return a + b

Можно посмотреть байткод этой функции через модуль dis:

import dis

dis.dis(add)

Вы увидите последовательность инструкций VM (LOAD_FAST, BINARY_ADD, RETURN_VALUE и т.п.), которая и есть байткод.

Модуль dis

Модуль dis занимается дизассемблированием байткода:

  • позволяет увидеть, во что компилятор превратил ваш высокоуровневый код;

  • помогает исследовать производительность, оптимизации, изменение семантики между версиями Python;

  • полезен при написании низкоуровневых оптимизаций или отладке «магии» (декораторы, метаклассы, автогенерируемый код).

Функция compile()

Встроенная compile() даёт явный доступ к шагу компиляции:

src = "a + b"
code_obj = compile(src, filename="", mode="eval")
result = eval(code_obj, {"a": 1, "b": 2})
print(result)  # 3

Она принимает строку кода, имя файла (для сообщений об ошибках) и режим (eval, exec, single) и возвращает объект code, который можно исполнять через eval/exec или исследовать.

Практические применения:

  • динамическая генерация кода (DSL, шаблоны, конфиги);

  • инструменты анализа (линтеры, форматтеры, статический анализ), которым нужен AST/байткод;

  • оптимизации с предкомпиляцией выражений.

Формулировка для собеседования

CPython — это стековая байткод‑виртуальная машина, написанная на C. Исходный код Python проходит парсинг и компиляцию в байткод, который хранится в объектах code и исполняется интерпретатором. Модуль dis позволяет посмотреть эти инструкции и понять, во что превращается ваш код. Функция compile() даёт программный доступ к шагу компиляции: можно из строки кода получить объект code и потом исполнять или анализировать его. На уровне senior важно уметь использовать эти механизмы хотя бы для диагностики и исследований.

Оцени свой прогресс

Честно оцени своё понимание этого вопроса, чтобы мы могли построить твой учебный трек максимально эффективно.
Читать в блоге