Python, интерпретаторы, байткод, .pyc, .pyo, .pyd, JIT и прочее


22.02.2020 — Про Python


Заголовок сочный, но как и говорил, всё очень кратко.

Давайте для начала примем, что Python - это интерфейс. Просто существует определённый набор того, что и как должно происходить, как должно себя вести.

Только выбрав имплементацию интерфейса уже можно говорить что-то о компиляции, байткоде и т.д. По дефолту такой реализацией является CPython - он же официальный (от самих разработчиков), он же самый популярный. Его и выберем, а о других просто будем знать, чтобы при необходимости заюзать.

Есть машинный код, а есть байткод. Машинный код прекрасен тем, что позволяет напрямую выполнять инструкции процессором. Байткод - некий промежуточный язык, понятный только виртуальной машине, которая и выполняет инструкции. Фишка машинного кода в том, что он дико быстрый, а байткода - возможность работать на разных платформах благодаря тому, что виртуальную машину можно написать для разных ОС и запускать один и тот же код везде. Так же байткод является более защищенным по очевидным причинам.

Дык вот CPython компилирует наш код в байткод. А потом выполняет его на своей виртуальной машине.

Собсна тоже самое и делает Java. У неё есть своя JVM, но почему-то она намного быстрее Python'a. Дело во многих вещах, но пока я затрону одно - JIT.

JIT - компиляция на лету. Фича в том, что у нас есть байткод, но было бы классно ещё и машинный местами использовать, чтобы ускорить выполнение. Этим и занимается Just in Time компиляция. Какие-то жирные куски, если есть возможность, она оптимайзит, компилирует в машинный код. Не всё так радужно, конечно. Ибо компиляция занимает время, но если выполнение и правда ускорится в разы, то это оправдано.

У JVM JIT есть, у CPython - нет. Обусловлено это тем, что CPython пытается быть всем и для всех. Из-за JIT программы долго запускаются. Если написать скрипт для выполнения в консоле, то нужен ли нам долгий запуск? Но CPython всего-лишь одна реализация интерфейса! И если мы точно знаем, что у нас, например, веб-приложение и мы запускаемся очень редко, а потом всё работаем и работаем - было бы классо иметь JIT и он у нас есть! В другой реализации - PyPy! Для JIT есть еще Numba. Кста, забыл упомянуть, что CPython позволяет прикрутить к себе JIT.

Сухой список реализаций Python'a:

- PyPy - написан на RPython, использует JIT, отлично совместим с CPython (а это позволяет запускать Django, Flask и другие проекты без каких-либо изменений).

  • Jython - компилирует наш python код в байткод для JVM (Java).
  • IronPython - C++.
  • Brython - JavaScript.
  • RubyPython - Ruby.

и т.д. и т.п.

Есть ещё Cython, который трында бустит код в связи с второй траблой плутона - динамической типизацией.

Вернёмся к CPython. Он правда компилирует. Результатом компиляции являются .pyc файлы, который вы можете встречать после запуска своих приложений. Хочу отметить, что данные файлы появляются только у модулей. Когда вы импортируете какой-либо другой файл, только в этом случае его байткод будет сохранён в файл! Когда вы устанавливаете пакеты, через setup.py там, например, то при установке весь пакет компилируется и рядом с оригинальными .py файлами появляются скомпилированные .pyc!

Нужда в перекомпиляции определяется по множеству критериев, но есть один основной - дата изменения файла. Если .py изменён раньше, чем создан .pyc, то будет использовал скопилированный байткод. Ну тут вылезают рофлы с таймзоной и т.д. Да и вообще, это "компиляция" бустит только скорость запуска.

С .pyc разобрались, переходим к .pyo. Данные файлы - это тоже самое, что и .pyc, только без относительного мусора. Фишка в том, что будут вырезаны инструкции необходимые, например, для дебага. Или убраны все docstrings. Для получения таких файлов необходимо запустить интерпритатор с аргом -O для первого случая и -OO для второго.

.pyd - всё ещё проще. Доступно только для шиндовса и знаете что это? Обычные DLL'ки! Да, конечно у вас в коде тогда должен быть метод, для точки входа и бла-бла, но по сути просто ддлка с парочкой отличий.

Недавние посты


© marshal.by 2020

Исходный код

Сайт работает на Gatsby + prismic и опубликован на GitHub.