Как устроен Python под капотом: полный разбор внутренней архитектуры CPython

Python кажется простым языком: написал строку — получил результат.
Но внутри работает сложная машина, состоящая из парсера, компилятора, виртуальной машины, менеджера памяти и целого набора низкоуровневых структур данных.
t.me/ai_machinelearning_big_data – мой тг канал, где я объяcняю сложные концепции и код с помощью короткий видео и картинок
Разберём всё по шагам.
1. Лексер и Парсер
Когда вы запускаете Python-файл, код проходит три этапа:
➤ 1) Лексер
Преобразует текст в токены: идентификаторы, числа, ключевые слова, операторы.
x = 1 + 2
Превращается в:
NAME(x)
EQUAL
NUMBER(1)
PLUS
NUMBER(2)
NEWLINE
➤ 2) Парсер
Токены собираются в синтаксическое дерево (AST — Abstract Syntax Tree).
Пример узла AST:
Assign(
targets=[Name(id='x')],
value=BinOp(1 + 2)
)
AST — структурированное дерево, описывающее, что именно делает программа.
2. Компилятор → Байткод (Bytecode)
CPython компилирует AST в байткод, который выполняет виртуальная машина Python.
Пример:
x = 1 + 2
Компилируется в:
LOAD_CONST 1
LOAD_CONST 2
BINARY_ADD
STORE_NAME x
Этот байткод хранится в объекте code object, который вы можете увидеть сами:
import dis
dis.dis(lambda: 1 + 2)
3. Виртуальная машина Python (Python Virtual Machine)
CPython — это стековая виртуальная машина.
Каждая инструкция байткода — маленькая операция, которая работает поверх стека.
Пример:
LOAD_CONST 1 → пушит 1 на стек
LOAD_CONST 2 → пушит 2
BINARY_ADD → снимает две верхние, складывает, кладёт обратно
STORE_NAME x → снимает верхнюю и привязывает к имени
Виртуальная машина — это цикл:
while True:
instruction = next opcode
execute(instruction)
Это называется Interpreter Loop или eval loop.
4. Объектная модель Python
Всё в Python — объект.
Даже числа, списки, функции — всё является структурой PyObject на C.
У каждого объекта есть:
- счётчик ссылок (для автоматического управления памятью)
- тип (PyTypeObject)
- реальные данные
Например, число 42 в CPython — это:
PyLongObject {
ob_refcnt = …
ob_type = &PyLong_Type
value = 42
}
5. Управление памятью: Reference Counting + GC
Python использует два механизма:
✓ 1) Reference Counting
Каждый объект хранит число ссылок.
Когда счётчик падает до нуля — объект уничтожается.
a = [1,2,3]
b = a
del a
del b # объект удалён
✓ 2) Garbage Collector (GC)
Нужен для обнаружения циклов, которые невозможно уничтожить через refcount.
GC работает поколениями (generational GC).
6. GIL — Global Interpreter Lock
Самая обсуждаемая особенность CPython.
GIL гарантирует, что одновременно байткод исполняет только один поток.
Проблемы:
- CPU-bound код не ускоряется потоками
- сложная конкуренция между потоками
Преимущества:
- простая безопасность памяти
- отсутствие race conditions внутри VM
- упрощённый C API
Для CPU задач используют:
- multiprocessing
- C-расширения без GIL
- PyPy, GraalPython, Mojo
7. Как работают модули и расширения
CPython легко расширяется — модули можно писать на C, C++ и Rust.
Пример C-функции:
static PyObject* add(PyObject* self, PyObject* args) {
int a, b;
PyArg_ParseTuple(args, "ii", &a, &b);
return PyLong_FromLong(a + b);
}
Такие модули выполняются намного быстрее, чем Python-код.
8. Как работает импорт
При импорте Python делает:
- ищет модуль в sys.modules
- ищет файл (py / pyc / so / dll)
- компилирует .py → .pyc
- загружает объект модуля
- выполняет код модуля
Bytecode кешируется в __pycache__/.
9. PyPy, Cython, Numba — другие механики исполнения
CPython — не единственная реализация.
PyPy
JIT-компилятор, умеет разгонять Python-код в 3–6 раз.
Cython
Статическая компиляция Python-подобного кода в C.
Numba
JIT-компиляция функций для вычислений (LLVM).
10. Почему Python медленный?
Причины:
- интерпретируемый байткод
- GIL блокирует параллельность
- каждый объект — тяжёлый PyObject
- динамическая типизация требует проверок
- VM использует стековые операции (дороже регистровых)
Но Python даёт скорость разработки, и тяжёлые участки легко вынести в C или Rust.
Итог: как Python выполняет ваш код
- Текст → токены
- Токены → AST
- AST → байткод
- ВМ исполняет байткод
- Объекты управляются refcount + GC
- GIL синхронизирует исполнение
- Модули и расширения ускоряют вычисления
Python прост снаружи, но внутри — это мощная и очень гибкая архитектура.



