CPython
| Тип | реализация языка программирования |
|---|---|
| Язык | Python |
| Написан на | C и Python |
| Разработчик | core-разработчики Python, Python Software Foundation |
| Управление памятью | подсчёт ссылок + циклический сборщик мусора |
| Репозиторий | github.com/python/cpython |
| Лицензия | PSF License |
CPython — эталонная и самая распространённая реализация языка Python, написанная на языке C. Именно её скачивают с python.org, именно она входит в дистрибутивы Linux и macOS, и именно в ней первыми появляются новые возможности языка. Название подчёркивает язык реализации и отличает её от альтернатив — PyPy, Jython, GraalPy, MicroPython.
История
CPython — исходная реализация, которую Гвидо ван Россум начал писать в 1989 году; название «CPython» появилось позже, когда возникли другие реализации. Долгое время проект жил в системе контроля версий Mercurial, а в 2017 году переехал на GitHub (PEP 512). Разработкой занимаются несколько десятков core-разработчиков, решения о крупных изменениях принимаются через PEP.
Как исполняется код
Запуск программы в CPython проходит несколько стадий:[1]
- Токенизация и разбор — исходный текст превращается в абстрактное синтаксическое дерево (AST). С версии 3.9 используется PEG-парсер.
- Компиляция — AST переводится в байт-код: последовательность инструкций стековой виртуальной машины, упакованных в объекты кода.
- Кеширование — байт-код импортируемых модулей сохраняется в файлы
.pycв каталоге__pycache__(PEP 3147), чтобы не компилировать их заново.[6] - Интерпретация — главный цикл (
ceval.c) выбирает инструкции по одной и исполняет их.
Байт-код можно посмотреть модулем dis:[7]
import dis
def add(a, b):
return a + b
dis.dis(add)
# RESUME 0
# LOAD_FAST_LOAD_FAST (a, b)
# BINARY_OP 0 (+)
# RETURN_VALUE
Точный набор инструкций меняется от версии к версии и не является частью спецификации языка.
Управление памятью
Каждый объект хранит счётчик ссылок; когда он падает до нуля, память освобождается немедленно. Это делает поведение предсказуемым (файл закрывается сразу после потери последней ссылки), но не справляется с циклами — например, двумя объектами, ссылающимися друг на друга. Для них работает дополнительный циклический сборщик мусора по поколениям (модуль gc). Подробнее — в статье Сборка мусора.
GIL и многопоточность
Подсчёт ссылок не потокобезопасен, поэтому исторически CPython защищает интерпретатор глобальной блокировкой (GIL): в каждый момент Python-байт-код исполняет только один поток. Потоки полезны для ввода-вывода (блокировка отпускается при ожидании), но не ускоряют вычисления на нескольких ядрах.
PEP 703 предложил сборку без GIL.[4] В версии 3.13 она появилась как экспериментальная (исполняемый файл python3.13t), в 3.14 получила статус официально поддерживаемой (PEP 779), хотя по умолчанию по-прежнему поставляется сборка с GIL.[5] Подробности — в статье GIL и free-threading (PEP 703).
Ускорение интерпретатора
Начиная с 3.11 проект Faster CPython заметно ускорил интерпретатор:
| Версия | Изменение |
|---|---|
| 3.11 | специализирующий адаптивный интерпретатор (PEP 659): «горячие» инструкции заменяются версиями под конкретные типы[2] |
| 3.12 | «бессмертные» объекты (PEP 683), отдельная блокировка на каждый субинтерпретатор (PEP 684) |
| 3.13 | экспериментальный JIT-компилятор по схеме copy-and-patch (PEP 744)[3], экспериментальная сборка без GIL |
| 3.14 | официально поддерживаемая сборка без GIL, модуль субинтерпретаторов в стандартной библиотеке |
C API и расширения
CPython предоставляет C API, через который пишутся модули расширения — так устроены NumPy, драйверы баз данных и многие быстрые библиотеки. Это источник силы экосистемы и одновременно ограничение: альтернативным реализациям трудно поддерживать совместимость с расширениями, завязанными на внутренности CPython. Для генерации расширений используют Cython, pybind11, а для Rust — PyO3.
Сравнение с другими реализациями
| Реализация | Особенность |
|---|---|
| CPython | эталон, максимальная совместимость с расширениями на C |
| PyPy | трассирующий JIT, быстрее на «чистом» Python, совместимость с C API частичная |
| MicroPython | урезанная реализация для микроконтроллеров |
| GraalPy | на GraalVM, взаимодействие с Java |
См. также
Источники
- Python Developer's Guide — Internals
- PEP 659 — Specializing Adaptive Interpreter
- PEP 744 — JIT Compilation
- PEP 703 — Making the Global Interpreter Lock Optional in CPython
- PEP 779 — Criteria for supported status for free-threaded Python
- PEP 3147 — PYC Repository Directories
- dis — Disassembler for Python bytecode