+7 (495) 147-04-32
Разработка приложений | LighTech
Главная
/
Блог
/
Разработчикам
/
Как на самом деле работает Python

Путешествие исходного кода: как на самом деле работает Python

Как на самом деле работает Python

Python часто воспринимается как язык, в котором всё происходит «само собой»: написал код — получил результат.  За таким «простым» процессом скрывается многоступенчатый механизм трансформации.

Каждая строка проходит через цепочку преобразований: от удобных человеку конструкций до инструкций, понятных машине. В этой статье разберёмся, как на самом деле работает Python под капотом и что происходит в тот момент, когда вы нажимаете run.

Что происходит после запуска python script.py

Когда вы вводите команду python script.py в терминале, запускается интерпретатор Python (стандартная реализация CPython). Выполнение кода python не начинается мгновенно — сначала происходит несколько подготовительных этапов.

Путь исходного кода Python

Python традиционно относят к интерпретируемым языкам, однако его работа сложнее: перед выполнением код компилируется в промежуточное представление — байт-код, который затем исполняется виртуальной машиной Python.

Разберём каждый этап подробно.

1. Компиляция: От текста к структурам данных

Первый этап работы CPython — компиляция исходного кода в байт-код. Он включает несколько последовательных шагов.
 

Токенизация (лексический анализ)

Исходный текст программы разбивается на минимальные значимые элементы — токены: ключевые слова, идентификаторы, операторы и скобки. На этом этапе игнорируются комментарии и незначащие пробелы, но отступы в Python являются частью синтаксиса.
 

Парсинг (синтаксический анализ)

Полученные токены преобразуются в абстрактное синтаксическое дерево (AST) — структуру, отражающую логику программы. Если в коде присутствуют синтаксические ошибки (например, пропущено двоеточие или нарушены отступы), они обнаруживаются именно на этом этапе.
 

Компиляция AST в байт-код

Затем компилятор CPython проходит по узлам AST и генерирует инструкции байт-кода — низкоуровневого представления программы, предназначенного для выполнения виртуальной машиной Python. Именно поэтому Python можно считать компилируемым языком в определённом смысле.

2. Байт-код: Язык виртуальной машины

Байт-код представляет собой низкоуровневый набор инструкций, не зависящий от архитектуры операционной системы или процессора. Он служит промежуточным звеном между исходным кодом и его выполнением.

Скомпилированные файлы сохраняются с расширением .pyc в директории __pycache__. Если исходный файл не изменялся, при последующих запусках Python использует уже готовый байт-код, что позволяет сократить время старта программы.

Байт-код — это не машинный код, исполняемый процессором. Он предназначен для выполнения внутри интерпретатора. Для преобразования Python-кода в нативный машинный код применяются дополнительные инструменты, такие как Cython или Nuitka.

3. PVM: Сердце интерпретатора

После генерации байт-кода управление передаётся Python Virtual Machine (PVM) — виртуальной машине, отвечающей за его выполнение. PVM представляет собой стековый интерпретатор, который последовательно считывает и исполняет инструкции байт-кода.

В основе её работы лежит стековая архитектура. Например, при сложении двух чисел значения сначала помещаются на стек, затем выполняется соответствующая операция, после чего результат возвращается на вершину стека и используется в дальнейших вычислениях.

4. Выполнение C-функций

Большинство повседневных операций, таких как конкатенация строк, работа со списками или математические вычисления со встроенными типами, реализовано в CPython на C.

Когда вы вызываете метод my_list.append(1), виртуальная машина Python (PVM) не интерпретирует логику добавления элемента на уровне Python. Вместо этого она обращается к оптимизированной функции на C, которая напрямую управляет памятью и выполняет операцию максимально эффективно. Такой подход позволяет сочетать удобство Python с производительностью низкоуровневых языков.

Почему Python считается медленным: основные причины

Вопрос производительности Python связан с его архитектурными особенностями. Чтобы лучше понять различия, сравним Python с компилируемыми языками, такими как C и C++.

  • C/C++: исходный код компилируется непосредственно в машинный код для конкретной архитектуры процессора. Полученный исполняемый файл взаимодействует с оборудованием напрямую, без промежуточных слоёв.
  • Python: код сначала компилируется в байт-код, после чего выполняется виртуальной машиной Python (PVM), что добавляет дополнительный уровень абстракции.
     

1. Динамическая типизация и проверки

В языках вроде C++ тип переменной известен на этапе компиляции. В Python же при каждой операции, например a + b, интерпретатор должен определить:

  •  типы операндов;
  • допустимость операции между ними;
  • соответствующий метод для выполнения (__add__ и др.).

Эти многочисленные проверки во время выполнения (runtime checks) создают дополнительные накладные расходы.
 

2. Интерпретация, а не компиляция в машинный код

PVM должна обрабатывать каждую инструкцию байт-кода прямо во время выполнения. Современные JIT-компиляторы (как в PyPy или V8 в JavaScript) пытаются это оптимизировать, но классический CPython работает именно так.
 

3. GIL (Global Interpreter Lock)

Это «замок», который позволяет только одному потоку управлять интерпретатором Python в единицу времени. Это упрощает управление памятью, но не даёт Python эффективно использовать многоядерные процессоры для параллельных вычислений в CPU-bound задачах.
 

4. Управление памятью

Python автоматически управляет памятью с помощью подсчёта ссылок (Reference Counting) и сборщика мусора (Garbage Collector). Хотя это избавляет разработчика от необходимости вручную освобождать ресурсы, такие механизмы требуют дополнительных вычислительных затрат.

Почему библиотеки (NumPy, Pandas) работают быстро?

Несмотря на медлительность чистого Python, библиотеки вроде NumPy, Pandas и TensorFlow работают в десятки раз быстрее. Секрет в том, их вычислительно тяжёлые части реализованы не на чистом Python.
 

Как ускоряют Python на практике

1. Библиотеки на C/C++/Rust. NumPy и Pandas используют массивы, и внутренние структуры данных, реализованные на низкоуровневых языках. Когда вы вызываете np.array([1, 2, 3]).sum(), Python делегирует вычисление быстрой C-функции, которая работает напрямую с памятью.

2. Векторизация операций. Вместо цикла for на Python, который медленно итерируется, NumPy выполняет операцию над всем массивом сразу через оптимизированный C-код.

3. Минимум проверок типов. В C-библиотеках типы данных фиксированы заранее (например, float64), поэтому не нужно проверять типы на лету.
 

Пример ускорения
 

# Медленно (чистый Python)
result = sum([i * 2 for i in range(1000000)])

# Быстро (NumPy, в 50-100 раз)
import numpy as np
result = np.sum(np.arange(1000000) * 2)

Python жертвует скоростью ради гибкости, но делегирует тяжёлые вычисления быстрым библиотекам.

Как работает Python и в чём его сила

Python изначально проектировался не как замена C или Java, а как язык, в котором код пишется быстро и читается легко. Скорость выполнения здесь намеренно принесена в жертву скорости разработки.

Многоуровневая архитектура добавляет накладные расходы, но даёт гибкость — один и тот же код работает на Windows, Linux и macOS без изменений. Там, где производительность критична, Python просто делегирует работу библиотекам на C, C++ других низкоуровневых языках (NumPy, pandas, PyTorch под капотом используют именно такие реализации).

Получается любопытная конструкция: вы пишете на Python, а тяжёлые вычисления выполняет скомпилированный код. Это объясняет, почему язык одинаково хорошо прижился и в веб-бэкенде, и в машинном обучении, и в научных расчётах — областях с совершенно разными требованиями к производительности.

Частые вопросы

Является ли Python компилируемым языком?
Зачем Python сохраняет .pyc файлы?

Поделиться

Обсудить проект с командой LighTech

Забронировать встречу

Примеры реализации проектов

Обсудить проект
Имя
Связаться
Сообщение
Прикрепить файл +
Запрос на получение файлов
Имя
Отправить файлы
Сообщение
Спасибо!
Ваша заявка отправлена
После обработки наш менеджер свяжется с вами