Разное

Компилятор для python: Online Python Compiler — online editor

Содержание

Онлайн-ide для Python. Как выбрать компилятор

Автор ArseniyDV На чтение 3 мин. Просмотров 14 Опубликовано

У всех, кто изъявил желание изучать «питон», прежде всего появляется вопрос — как сделать это онлайн и что для этого нужно? В статье мы поделимся списком нужных ресурсов и дадим несколько советов, чтобы обучение Python online протекало немного легче и быстрее.

Online IDE Compiler для Python или как выбрать компилятор для «Питона»

Существует много характеристик, по которым пользователи выбирают себе тот или иной ресурс. Это и поддержка внешних библиотек, и возможность изменять внешний вид кода (шрифт, цвет), и цена пользования, а также многие другие функции. Ниже мы собрали список тех онлайн интерпретаторов Python, заевовавших большее доверие у своих пользователей.

Топ 5 онлайн компиляторов для Python

Python Fiddle

Один из самых удобных онлайн компиляторов (можно использовать и для Python 3). Интерфейс сайта очень легок в использовании. Левая панель данного онлайн интерпретатора «питона» оснащена не одним примером кода, изучая которые можно открыть для себя что-то новое.

Важно! Здесь можно делиться своим кодом, что выручает, если вы обучаетесь с кем-то еще (другом или преподавателем).

Python Anywhere

Обладает множеством полезных функций, которые довольно тяжело отыскать на других ресурсах. Также поддерживает IPython и Python 3, являясь лучшим online компилятором для них.

Codechef

Считается одним из наиболее универсальных ресурсов. Оснащена большим разнообразием функции (автоматическое дополнение, изменение темы редактора и т.д.).

Обратите внимание, что этот онлайн интерпретатор можно использовать не только для «питон», но и для других языков.

Codeanywhere

По отзывам, является одной из лучших сред для программирования. Этот онлайн интерпретатор, помимо Python 3, поддерживает еще более 70 языков! Регистрация довольно быстрая, есть возможность подключиться к FTP, Google Drive и т. п.

Trinket

Помимо стандартных возможностей, обладает возможностью запуска исходников. Бесплатная версия особыми ограничениями не обладает, однако не подойдет, если вы собирались использовать данный ресурс в качестве онлайн интерпретатора Python 3. Для этого придется покупать платную версию (9 долларов в месяц).

Какой наилучший онлайн компилятор для Python 3?

Здесь, как говорится, на вкус и цвет. Вы можете попробовать каждый из представленных нами выше онлайн компиляторов для Python 3, например, а затем сделать выбор в пользу того ресурса, с которым вам было удобнее всего работать.

Где можно выучиться на Python-разработчика

Вы можете поискать различные онлайн-курсы, чтобы сократить себе путь и новичка в человека, владеющего Python на высшем уровне. Если бюджет ограничен, в помощь придут различные обучающие сайты, блоги, а также видео на Youtube.

Советы для изучения «Питона»

Изучать «питон» онлайн, как и любой язык программирования — не самая легкая задача. Для этого вам понадобится запастись терпением и большим желанием. Поставьте себе ограниченную по времени цель, расклейте стикеры-напоминания, расскажите друзьям о своем новом увлечении.

Можете попробовать найти кого-то, кто захочет изучать Python с вами, ведь вдвоем гораздо веселее!

И самое главное: не бойтесь ошибаться и пробовать еще раз, ведь как известно, не ошибается только тот, кто ничего не делает. Успехов в программировании!

Ускоряем Python — 4 быстрых компилирующих транслятора для Python

Эта статья является переводом и адаптацией оригинальной англоязычной статьи авторства Дэвида Болтона.

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

Однако, по мере того, как язык набирает популярность, разработчики хотят создавать и быстро работающие программы на Python, поэтому за последние годы появилось несколько компиляторов Python, включая IronPython и Jython.

От переводчика: Python широко используется как для создания традиционных приложений, например, веб-сервисов, так и для приложений машинного обучения и обработки больших данных, которые используют язык только для управления потоком обработки, при этом сама обработка происходит в рамках расширений, которые реализованы на C. Однако, даже в случае последнего сценария использования, часть кода, которая выполняется в рамках Python может существенно замедлить все приложение, в связи с чем появились дополнительные способы расширения языка, например, Numba.

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

Я хотел сравнить несколько компиляторов Python на одной платформе, особенно те, которые поддерживают Python 3.x. В итоге я выбрал четыре, все они работают на Ubuntu Linux: Nuitka, PyPy, Cython и cx_Freeze.

Сравнение трансляторов Python

В качестве бенчмарка будет использоваться пакет PyStone, адаптация C-программы, которую сделал Гвидо ван Россум, создатель Python (сама C-программа была переводом Ада-программы). Я нашел версию бенчмарка от Кристофера Арндта, которая способна тестировать Python 3. Чтобы получить представление о базовой производительности, оценим производительность CPython (то есть стандартного Python) с PyStone.

Все бенчмарки при переводе были выполнены заново на CPU Intel(R) Core(TM) i5-7440HQ CPU @ 2.80GHz

$ python2 pystone.py 1000000
Pystone(1.1.1) time for 1000000 passes = 3.61152
This machine benchmarks at 276892 pystones/second

$ python3 pystone.py 1000000
Pystone(1.1.1) time for 1000000 passes = 4.07254
This machine benchmarks at 245547 pystones/second

Как видите, между производительностью теста в Python 2 и 3 есть существенная разница (чем больше Pystones в секунду, тем лучше). В следующих разбивках все компиляторы используют Python 3.

Nuitka

В Ubuntu 18.04 установить Nuitka возможно с помощью APT:

$ sudo apt update
$ sudo apt install nuitka clang

Результат выполнения бенчмарка для компилятора Nuitka:

# Сборка для GCC
$ nuitka pystone. py
$ ./pystone.exe 1000000
Pystone(1.1.1) time for 1000000 passes = 2.67537
This machine benchmarks at 373780 pystones/second

# Сборка для Clang
$ nuitka pystone.py --clang
$ ./pystone.exe 1000000
Pystone(1.1.1) time for 1000000 passes = 2.64646
This machine benchmarks at 377863 pystones/second

# Использование GCC с оптимизацией 
$ nuitka pystone.py --lto
$ ./pystone.exe 1000000
Pystone(1.1.1) time for 1000000 passes = 2.6195
This machine benchmarks at 381753 pystones/second

Как можно видеть, Nuitka позволила получить увеличение производительности на 50%, по сравнению со стандартной реализацией Python 3.

PyPy

Гидо ван Россум однажды сказал: «Если вы хотите, чтобы ваш код работал быстрее, вам, вероятно, следует просто использовать PyPy». Я загрузил переносимые двоичные файлы в папку, а в папке bin скопировал pystone.py. Затем я запустил это так: Мы просто установили PyPy 3 с помощью Ubuntu Snap:

$ sudo snap install pypy3 --classic

Результаты бенчмарка:

$ pypy3 pystone. py 1000000
Pystone(1.1.1) time for 1000000 passes = 0.359845
This machine benchmarks at 2.77897e+06 pystones/second

$ pypy3 pystone.py 1000000
Pystone(1.1.1) time for 1000000 passes = 0.26776
This machine benchmarks at 3.73469e+06 pystones/second

$ pypy3 pystone.py 1000000
Pystone(1.1.1) time for 1000000 passes = 0.147859
This machine benchmarks at 6.7632e+06 pystones/second

Для данного теста результаты выполнения до «разгона» показывают более 10 кратное, а после «разгона» более чем 26 кратное ускорение производительности.

Создание исполняемого файла требует больше работы. Вы должны написать свой Python в подмножестве RPython.

Cython

Cython — это не просто компилятор для Python; это языковое надмножество языка Python, который поддерживает взаимодействие с C/C ++. CPython написан на C, поэтому это язык, который обычно хорошо сочетается с Python:

$ sudo apt install cython3 pkg-config

Сборка программы с помощью Cython немного сложна. Это не похоже на Nuitka, которая просто работает из коробки:

$ cython3 pystone.py --embed
$ gcc $(python3-config --includes) pystone.c -lpython3.6m -o pystone.exe


$ ./pystone.exe 1000000
Pystone(1.1.1) time for 1000000 passes = 4.8549
This machine benchmarks at 205978 pystones/second

Производительность оказалась весьма низкой, гораздо ниже, чем у стандартного CPython. Однако, Cython требует, чтобы вы проделали дополнительную работу, указав типы переменных. Python — это динамический язык, поэтому типы не указываются; Cython использует статическую компиляцию, а использование переменных с типом Си позволяет создавать гораздо более оптимизированный код — документация довольно обширна и требует глубокого изучения.

Cx_Freeze

Cx_freeze — это набор скриптов и модулей для «замораживания» скриптов Python в исполняемые файлы. Установить cx_Freeze можно с помощью PIP3:

sudo pip3 install cx_Freeze --upgrade
$ cxfreeze pystone.py -O -s --target-dir dist
Missing modules:
? __main__ imported from bdb, pdb
? _dummy_threading imported from dummy_threading
? _frozen_importlib imported from importlib, importlib.abc
? _frozen_importlib_external imported from importlib, importlib._bootstrap, importlib.abc
? _winapi imported from subprocess
? _winreg imported from platform
? java.lang imported from platform
? msvcrt imported from subprocess
? nt imported from ntpath, os, shutil
? org.python.core imported from copy, pickle
? os. path imported from os, pkgutil, py_compile, tracemalloc, unittest, unittest.util
? vms_lib imported from platform
? winreg imported from mimetypes, platform
This is not necessarily a problem - the modules may not be needed on this platform.

Copying data from package collections...
Copying data from package email...
Copying data from package encodings...
Copying data from package html...
Copying data from package http...
Copying data from package importlib...
Copying data from package logging...
Copying data from package pydoc_data...
Copying data from package unittest...
Copying data from package urllib...
Copying data from package xml...

$ dist/pystone 1000000
Pystone(1.1.1) time for 1000000 passes = 5.35072
This machine benchmarks at 186891 pystones/second

Как можно видеть, производительность даже ниже, чем у стандартного интерпретатора CPython. Данное решение разумно использовать только для упаковки всего Python-окружения в независимый исполняемый пакет. Стоит отметить, что для этой цели можно использовать и Pyinstaller.

Заключение

Я в восторге от производительности PyPy. Компиляция была очень быстрой, и приложение работало в десятки раз быстрее аналогов и оригинального кода CPython. Если вы хотите распространять бинарный файл, выбирайте Nuitka — решение дает как ускорение, так и позволяет выполнить упаковку кода.

От переводчика: в статье рассмотрено использование решений PyPy, Nuitka, Cython и Cx_Freeze для очень простого кода, который без проблем собирается данными трансляторами. Код, используемый в реальных приложениях, может быть затруднительно скомпилировать или его производительность может стать еще хуже, чем у стандартного Python. Необходимо производить бенчмарки на том коде, который вы собираетесь распространять, поскольку синтетические бенчмарки, как в этой статье не дают представления о реальном варианте использования, который будет в вашем случае.

ускоряем Python с минимальными усилиями

Перевод публикуется с сокращениями, автор оригинальной статьи Jahongir Rahmonov.

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

PyPy – это совместимый интерпретатор Python и достойная
альтернатива CPython 2.7, 3.6, а вскоре и 3.7. Запустив приложение с его помощью, можно получить заметные улучшения скорости.

Спецификация Python используется
в ряде реализаций, таких как CPython (написанный на C), Jython (написанный на Java), IronPython (написанный для . NET) и PyPy (написанный на Python).

CPython – оригинальная реализация, которая на
сегодняшний день является самой популярной и поддерживаемой. Поскольку это
высокоуровневый интерпретируемый язык, CPython имеет определенные ограничения и
тут поможет PyPy. Он соответствует спецификации Python и не требует изменений в
коде.

Ваша ОС из коробки должна предоставлять пакет PyPy. На macOS,
например, он инсталлируется с помощью Homebrew:

        brew install pypy3
    

Если нет, придется скачать готовый бинарник для вашей операционной системы. После завершения загрузки просто распакуйте архив
и можете не устанавливая использовать PyPy в любом месте:

        $ tar xf pypy3. 6-v7.3.1-osx64.tar.bz2
$ ./pypy3.6-v7.3.1-osx64/bin/pypy3
Python 3.6.9 (?, Jul 19 2020, 21:37:06)
[PyPy 7.3.1 with GCC 4.2.1]
Type "help", "copyright", "credits" or "license" for more information.
    

Выполнять команды нужно внутри папки, в которую вы загрузили двоичный файл.
Полную инструкцию вы найдете в документации по установке.

Чтобы увидеть PyPy в действии, создайте файл Python с именем script.py и поместите в
него следующий код:

        total = 0
for i in range(1, 10000):
    for j in range(1, 10000):
        total += i + j

print(f"The result is {total}")
    

Скрипт из двух вложенных циклов for добавляет числа от 1 до
9999 и выводит результат. Чтобы узнать, сколько времени потребуется для его выполнения, добавьте выделенные строки:

        import time

start_time = time.time()

total = 0
for i in range(1, 10000):
    for j in range(1, 10000):
        total += i + j

print(f"The result is {total}")

end_time = time.time()
print(f"It took {end_time-start_time:.2f} seconds to compute")
    

Теперь код выполняет следующие действия:

  • Строка 3 сохраняет значение текущего времени в переменной start_time;
  • Строки с 5 по 8 выполняют циклы;
  • Строка 10 выводит результат;
  • Строка 12 сохраняет время в end_time;
  • Строка 13 выводит разницу между start_time и end_time, чтобы показать, сколько времени потребовалось для выполнения скрипта.

Попробуйте запустить его с помощью Python. Вот что я получаю на MacBook Pro 2015 года:

        $ python3.6 script.py
The result is 999800010000
It took 20.66 seconds to compute
    

Теперь запустим сценарий с помощью PyPy:

        $ pypy3 script.py
The result is 999800010000
It took 0.22 seconds to compute
    

Этот синтетический тест показывает, что PyPy примерно в 94
раза быстрее Python. Для более серьезной проверки взгляните на PyPy
Speed Center, где разработчики запускают ночные тесты с различными
исполняемыми параметрами. Нужно помнить, что производительность PyPy напрямую зависит
от того, что делает ваш код.

Исторически сложилось так, что PyPy связан с двумя сущностями:

  • Языковым фреймворком RPython для создания интерпретаторов динамических языков;
  • Реализацией Python с использованием этого фреймворка.

Причина, по которой PyPy известен, как написанный на Python (а не на RPython) интерпретатор, заключается в следующем: RPython
использует тот же синтаксис, что и Python. Давайте разберемся, как разрабатывается PyPy:

  • Исходный код написан на RPython;
  • Инструменты RPython (translation toolchain) применяются к коду, делая его более эффективным. Они компилируют код в машинный, поэтому под Mac, Windows и Linux необходимы разные версии;
  • Создается двоичный исполняемый файл – интерпретатор Python, который мы использовали для запуска скрипта.

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

Далее мы изучим функции, делающие PyPy таким эффективным.

Just-In-Time (JIT) компилятор

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

Компилируемые ЯП более производительны, но их сложно портировать
на различные архитектуры и ОС. Интерпретируемые ЯП лучше портируются, но их
производительность намного хуже.

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

Однако производительность по-прежнему далека от компилируемой
версии, поскольку та способна выполнять множество невозможных для байт-кода оптимизаций. Здесь появляется JIT-компилятор, объединяющий лучшие части обоих миров.
Рассмотрим шаги JIT-компиляции, необходимые для обеспечения производительности:

  • определение наиболее часто используемых компонентов кода, вроде функции в цикле;
  • преобразование этих частей в машинный код во время выполнения;
  • оптимизация сгенерированного машинного кода;
  • замена предыдущей реализации оптимизированной версией машинного кода.

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

Сборщик мусора

Всякий раз, когда вы создаете любые объекты, под них выделяется
память. Если неиспользуемые объекты не чистить, память закончится и произойдет сбой программы.

В C и C++ проблему обычно приходится решать вручную.
Другие языки программирования, вроде Python и Java, делают это автоматически. Процесс называется
автоматической сборкой мусора – существует несколько методов ее выполнения.

В CPython счетчик ссылок на
объект увеличивается всякий раз, когда на него ссылаются и уменьшается при разыменовании.
Когда счетчик равен нулю, CPython автоматически вызывает функцию освобождения
памяти для объекта, но есть один нюанс. Когда количество ссылок большого
дерева объектов становится равным нулю, все связанные объекты освобождаются. Возможна длинная пауза, во время которой программа простаивает. Есть также вариант, при котором подсчет ссылок не сработает.
Рассмотрим следующий код:

        class A(object):
    pass

a = A()
a.some_property = a
del a
    

В приведенном коде определяется новый класс, создается экземпляр, его свойству присваивается ссылка на себя, а экземпляр удаляется.

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

В этом случае CPython использует другой инструмент – циклический
сборщик мусора. Он пробегает по всем объектам в памяти, идентифицирует доступные и освобождает недостижимые, поскольку они больше не
активны. Это исправляет проблему с циклом ссылок, однако могут появиться
заметные паузы, когда в памяти находится большое количество объектов.

PyPy использует только второй метод. Он
периодически ходит по «живым» объектам, начиная с корня. Это дает ему
преимущество перед CPython, делая меньше затраченное на
управление памятью время. Вместо того, чтобы делать все за один подход, PyPy разбивает работу на части. Такой подход добавляет всего несколько
миллисекунд после каждой коллекции, а не сотни, как в CPython.

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

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

Некорректная работа с C-Extensions

Всякий раз, когда вы используете С-расширения, программа будет
работать намного медленнее чем в CPython, т. к. они не поддерживаются полностью, и PyPy не может их оптимизировать. Также PyPy должен эмулировать подсчет
ссылок для этой части кода, что делает его еще более медленным.

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

Разработчики трудятся над C-Extensions: некоторые пакеты уже
портированы на PyPy и работают так же быстро.

Работает только с Long-Running программами

Когда вы запускаете скрипт с помощью PyPy, он совершает много
операций, чтобы код работал быстрее. Если скрипт слишком мал, из-за накладных расходов он будет работать медленнее, чем в CPython. С
другой стороны, если код большой, эти накладные расходы могут увеличить производительность.

Чтобы в этом убедиться, выполните следующий небольшой скрипт в
CPython и PyPy:

        import time

start_time = time.time()

for i in range(100):
    print(i)

end_time = time.time()
print(f"It took {end_time-start_time:.10f} seconds to compute")
    

Есть небольшая задержка, когда вы запускаете его с помощью
PyPy, в то время как в CPython старт происходит мгновенно. На MacBook Pro использование
CPython займет 0.0004873276 секунды, а в случае с PyPy – 0.0019447803 секунды.

Он не делает компиляцию заранее

PyPy не является полностью компилируемой реализацией
Python. Из-за
присущего Python динамизма, код невозможно скомпилировать в двоичный файл и
повторно его использовать.

PyPy – это рантайм-интерпретатор, который работает быстрее,
чем полностью интерпретируемый язык, но медленнее, чем полностью
компилируемый.

PyPy – это быстрая и эффективная альтернатива CPython.
Запустив свой скрипт с его помощью, вы можете получить значительное улучшение
скорости, не внося ни одного изменения в код. У него есть ограничения, и вам
нужно будет протестировать программу, чтобы проанализировать целесообразность
использования альтернативного интерпретатора.

Дополнительные материалы:

Зачем компилировать код Python? | Блог о программировании

плюсы:

во-первых: мягкая, поражаемая обфускация.

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

третье: Python может пропустить шаг компиляции. Быстрее при начальной нагрузке. Хорошо для процессора и интернета.

четвертое: чем больше вы комментируете, тем меньше .pyc или .pyo файл будет по сравнению с исходным .py файл.

пятое: конечный пользователь только с .pyc или .pyo файл в руке гораздо менее вероятно, чтобы представить вам с ошибкой, которую они вызвали необратимого изменения они забыли сказать вам о.

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

верхний уровень компиляция

полезно знать, что вы можете скомпилировать исходный файл python верхнего уровня в . pyc файл таким образом:

python -m py_compile myscript.py

это удаляет комментарии. Он уходит docstrings нетронутыми. Если вы хотите избавиться от docstrings а также (вы можете серьезно подумать о том, почему вы это делаете), а затем скомпилировать этот способ вместо этого…

python -OO -m py_compile myscript.py

…и вы получите вместо .pyc файл; одинаково распространяемый с точки зрения основная функциональность кода, но меньше по размеру урезанного docstrings (и менее легко понять для последующего трудоустройства, если он имел приличный docstrings в первую очередь). Но смотрите недостаток три, ниже.

обратите внимание, что Python использует .py дата файла, если она присутствует, чтобы решить, следует ли выполнить .py файл в отличие от .pyc или .pyo file — — — поэтому отредактируйте свой файл. py и .pyc или .pyo устарел и все, что приносит вам пользу приобретенное теряется. Вам нужно перекомпилировать его, чтобы получить .pyc или .pyo преимущества снова снова, такие как они могут быть.

недостатки:

во-первых: есть «волшебное печенье» в .pyc и .pyo файлы, указывающие на системную архитектуру, в которой был скомпилирован файл python. Если вы распространяете один из этих файлов в среде другого типа, он сломается. Если вы распространяете .pyc или .pyo без соответствующего .py перекомпилировать или touch таким образом, он заменяет .pyc или .pyo конечный пользователь не может исправить это.

Во-Вторых: Если docstrings пропускаются с использованием -OO опция командной строки как описано выше, никто не сможет получить эту информацию, что может сделать использование кода более сложным (или невозможным. )

в-третьих: в Python также реализует некоторые оптимизации в соответствии с -O параметр командной строки; это может привести к изменения в работе. Известные оптимизации:

  • sys.flags.optimize = 1
  • assert высказывания пропускаются
  • __debug__ = False

четвертое: Если вы намеренно сделали свой скрипт python исполняемым с чем-то по порядку #!/usr/bin/python на первой строке это вычеркнуто в .pyc и .pyo файлы и функциональность не теряется.

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

Как работает Python? / Мастерская интернет-разработчика

22 августа 2009 г.

Windows

Python

FreeBSD

Всем еще раз привет, сейчас расскажу о том, как работает Python, что такое интерпретатор, как работает компилятор и что такое байт-код, далее расскажу о виртуальной машине (PVM) и о производительности Python. Также о альтернативных реализациях интерпретатора.

После того, как вы установили себе Python, перейдем к теоретически-практической части и начнем с того что из себя представляет интерпретатор.

Интерпретатор

Интерпретатор — это такая программа, которая выполняет другие программы. Когда вы пишете программу на языке Python, интерпретатор читает вашу программу и выполняет содержащиеся в ней инструкции. В действительности, интерпретатор — это слой программной логики между вашим программным кодом и аппаратурой вашего компьютера.

В зависимости от используемой версии Python сам интерпретатор может быть реализован как программа на языке C, как набор классов Java и в каком-либо другом виде, но об этом позже.

Запуск сценария в консоли

Давайте запустите в консоле интерпретатор:

# python 

Теперь он ожидает ввода комманд, введите туда следующую инструкцию:

print 'hello world!'

ура, наша первая программа! 😀

Запуск сценария из файла

Создайте файл «test. py», с содержимым:

# вывести "hello world"
print "hello world"

# вывести 2 в 10 степени
print 2 ** 10

и выполните этот файл:

# python /path/to/test.py

Вы увидите в консоли результат, поехали дальше!

Динамическая компиляция и байт-код

После того, как запустите сценарий, Python сначала компилирует исходный текст сценария в байт-код для виртуальной машины. Компиляция — это просто этап перевода, а байт-код это низкоуровневое платформонезависимое представление исходного текста программы. Python транслирует каждую инструкцию в исходном коде сценария в группы инструкций байт-кода для повышения скорости выполнения программы, так как байт-код выполняется намного быстрее. После компиляции в байт-код, создается файл с расширением «.pyc» по соседству с исходным текстом сценария.

В следующий раз, когда вы запустите свою программу интерпретатор минует этап компиляции и отдаст на выполнение откомпилированный файл с расширением «. pyc». Однако, если вы изменили исходные тексты вашей программы, то снова произойдет этап компиляции в байт-код, так как Python автоматически следит за датой изменения файла с исходным кодом.

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

Виртуальная машина Python (PVM)

После того как пройдет процесс компиляции, байт-код передается механизму под названием виртуальная машина, которая и выполнит инструкции из байт-кода. Виртуальная машина — это механизм времени выполнения, она всегда присутствует в составе системы Python и это крайняя составляющая системы под названием «Интерпретатор Python».

Для закрепления пройденного еще раз проясним ситуацию, компиляция в байт-код производится автоматически, а PVM — это всего лишь часть системы Python, которую вы установили вместе с интерпретатором и компилятором. Все происходит прозрачно для программиста, и вам не надо выполнять эти операции вручную.

Производительность

Программисты имеющие опыт работы с такими языками как C и C++, могут заметить некоторые отличия в модели выполнения Python. Первое — это отсутствие этапа сборки или вызова утилиты «make», программы на Python могут быть сразу же запущены после написания исходного кода. Второе отличие — байт-код не является двоичным машинным кодом (например инструкции для микропроцессора Intel), он является внутренним представлением программы на языке Python.

По этим причинам программы на Python не могут выполняться также быстро как на C/C++. Обход инструкций выполняет виртуальная система, а не микропроцессор, и чтобы выполнить байт-код, необходима дополнительная интерпретация, инструкции которой требуют большего времени, чем машинные инструкции микропроцессора.

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

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

Альтернативные реализации Python

То что было сказано выше о компиляторе и виртуальной машине, характерно для стандартной реализации Python, так называемой CPython (реализации на ANSI C). Однако также существует альтернативные реализации, такие как Jython и IronPython, о которых пойдет сейчас речь.

CPython

Это стандартная и оригинальная реализация Python, названа так, потому что написана на ANSI C. Именно ее мы установили, когда выбрали пакет ActivePython или установили из FreeBSD портов. Поскольку это эталонная реализация, она как правило работает быстрее, устойчивее и лучше, чем альтернативные реализации.

Jython

Первоначальное название JPython, основная цель — тесная интеграция с языком программирования Java. Реализация Jython состоит из Java-классов, которые выполняют компиляцию программного кода на языке Python в байт-код Java и затем передают полученный байт-код виртуальной машине Java (JVM).

Цель Jython состоит в том, чтобы позволить программам на языке Python управлять Java-приложениями, точно также как CPython может управлять компонентами на языках C/C++. Эта реализация имеет беcшовную интеграцию с Java. Поскольку программный код на Python транслируется в байт-код Java, во время выполнения он ведет себя точно также, как настоящая программа на языке Java. Программы на Jython могут выступать в качестве апплетов и сервлетов, создавать графический интерфейс с использованием механизмов Java и т.д. Более того, Jython обеспечивает поддержку возможности импортировать и использовать Java-классы в программном коде Python.

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

IronPython

Реализация предназначена для обеспечения интеграции программ Python с приложениями, созданными для работы в среде Microsoft . NET Framework операционной системы Windows, а также в Mono — открытом эквиваленте для Linux. Платформа .NET и среда выполнения языка C# предназначены для обеспечения взаимодействия между программными объектами — независимо от используемого языка программирования, в духе более ранней модели COM компании Microsoft.

IronPython позволяет программам на языке Python играть роль как клиентских, так и серверных компонентов, доступных из других языков программирования .NET. Поскольку разработка ведется компанией Microsoft, от IronPython, помимо прочего, можно было бы ожидать существенной оптимизации производительности.

Средства оптимизации скорости выполнения

Существуют и другие реализации, включая динамический компилятор Psyco и транслятор Shedskin C++, которые пытаются оптимизировать основную модель выполнения.

Динамический компилятор Psyco

Система Psyco — это компонент, расширяющий модель выполнения байт-кода, что позволяет программам выполняться быстрее. Psyco является расширением PVM, которое собирает и использует информацию о типах, чтобы транслировать части байт-кода программы в истинный двоичный машинный код, который выполняется гораздо быстрее. Для такой трансляции не требуется вносить изменения в исходный код или производить дополнительную компиляцию в ходе разработки.

Во время выполнения программы, Psyco собирает информацию о типах объектов, и затем эта информация используется для генерации высокоэффективного машинного кода, оптимизированного для объектов этого типа. После этого произведенный машинный код заменяет соответствующие участки байт-кода, тем самым увеличивается скорость выполнения.

В идеале некоторые участки программного кода под управление Psyco могут выполняться также быстро, как скомпилированный код на языке Си.

Psyco обеспечивает увеличение скорости от 2 до 100 раз, но обычно в 4 раза, при использовании немодифицированного интерпретатора Python. Единственный минус у Psyco, это то обстоятельство, что в настоящее время он способен генерировать машинный код только для архитектуры Intel x86.

Psyco не идет в стандартной поставке, его надо скачать и установить отдельно. Еще есть проект PyPy, который представляет собой попытку переписать PVM с целью оптимизации кода как в Psyco, проект PyPy собирается поглотить в большей мере проект Psyco.

Транслятор Shedskin C++

Shedskin — это система, которая преобразует исходный код на языке Python в исходный код на языке C++, который затем может быть скомпилирован в машинный код. Кроме того, система реализует платформонезависемый подход к выполнению программного кода Python.

Фиксированные двоичные файлы (frozen binaries)

Иногда необходимо из своих программ на Python создавать самостоятельные исполняемые файлы. Это необходимо скорее для упаковки и распространения программ.

Фиксированные двоичные файлы объединяют в единый файл пакета байт-код программ, PVM и файлы поддержки, необходимые программам. В результате получается единственный исполняемый файл, например файл с расширение «.exe» для Windows.

На сегодняшний день существует три основных инструмента создания «frozen binaries»:

  • py2exe — он может создавать автономные программы для Windows, использующие библиотеки Tkinter, PMW, wxPython и PyGTK для создания графического интерфейса, программы использующие программные средства создания игр PyGame, клиентские программы win32com и многие другие;
  • PyInstaller — напоминает py2exe, но также работает в Linux и UNIX и способен производить самоустанавливающиеся исполняемые файлы;
  • freeze — оригинальная версия.

Вам надо загружать эти инструменты отдельно от Python, они распространяются бесплатно.

Фиксированные двоичные файлы имеют немалый размер, ибо они содержат в себе PVM, но по современным меркам из все же нельзя назвать необычно большими. Так как интерпретатор Python встроен непосредственно в фиксированные двоичные файлы, его установка не является обязательным требованием для запуска программ на принимающей стороне.

Резюме

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

Как скомпилировать python приложение? — Toolmark

Вот вы написали какой-нибудь скрипт на python. Вы можете запустить его у себя на компе, т.к. у вас установлен python. Если вы этот скрипт скинете своему другу, то у него он скорее всего работать не будет, т.к. на его компьютере не установлен python. Что делать?

В программирование есть понятие «компилирование», если объяснить очень просто, то компилирование это перевод нашего скрипта, написанного на языке Python на более низкоуровневый язык программирования, так называемый машинный код. После компиляции мы получим exe файл, который сможем запустить на любом компьютере, где не установлен python.

В этой статье мы продолжим работу со скриптом, который я написал в одной из предыдущих статей. Этот скрипт подключается к api сайта hh.ru и считает среднюю зарплату по запросу “интернет маркетолог”. Я немного модифицировал его, теперь он будет считать среднюю зарплату по любому запросу. Для этого перед исполнением программы, вы должны будете ввести запрос, по которому он посчитает среднюю ЗП.

Для компилирования нам понадобится специальный пакет pyinstaller. Установим его при помощи менеджера пакетов pip

Вводим в консоль команду

После этого в консоли переходим в директорию где хранится ваш скрипт, в моём случае это рабочий стол, я ввожу в консоль

cd C:\Users\Админ\Desktop



cd C:\Users\Админ\Desktop

Теперь вводим команду и жмем энтер

av_zp. py это название моего скрипта, вам нужно указать своё название

В результате в папке где находится скрипт у нас появляются 4 новых файла, см. скрин (выделены красной рамкой)

Здесь нас интересует папка dist, остальное можно удалить. В папке у нас появилось приложение av_zp.exe. Давайте запустим его.

Наше приложение работает через консоль у него нет графического интерфейса. После запуска приложение напишет “Введите название вакансии”. Введите название вакансии по которой вы хотите узнать среднюю ЗП и нажмите энтер. Приложению может понадобиться 30-60 сек , чтобы собрать данные с сайт hh.ru после этого одно выдаст вам строку с ответом.

Ниже скрин с примером работы программы.

Вот ссылка на приложение, можете скачать себе на комп и поэкспериментировать

Функция Python compile () — JournalDev

Функция Python compile () используется для компиляции исходного кода в объект кода или объект модуля AST. Возвращенный объект кода может быть выполнен с использованием функции exec () или eval () в зависимости от предоставленного режима для создания объекта кода.

Python compile ()

Синтаксис функции Python compile ():

 
компиляция (источник, имя файла, режим, флаги = 0, dont_inherit = False, optimize = -1)
  

Давайте посмотрим на аргументы функции compile ().

  • источник : Источник для создания объекта кода. Это может быть строка, байтовая строка или объект модуля AST.
  • имя_файла : Если вы читаете строку кода из файла, вы должны указать здесь его имя для справки. Он не используется при создании объекта кода, а используется для обеспечения читабельности кода.
  • режим : этот аргумент указывает тип кода. Допустимые значения: exec , eval и single .Используйте exec, если источник содержит несколько операторов Python. Используйте eval, если источник — это одно выражение Python. Используйте один, если источник состоит из одного интерактивного оператора.
  • Необязательные аргументы flags и dont_inherit управляют тем, какие будущие операторы влияют на компиляцию исходного кода. Если ни один из них не присутствует (или оба равны нулю), код компилируется с теми будущими операторами, которые действуют в коде, вызывающем compile ().
  • Аргумент optimize указывает уровень оптимизации компилятора.

Python compile () examples

Давайте посмотрим на пример функции compile () с разными источниками.

Компиляция исходного кода строки в код

 
# compile () со строковым источником
code_str = 'x = 5 \ ny = 10 \ nprint ("sum =", x + y)'
код = компиляция (code_str, 'sum.py', 'exec')
печать (тип (код))
exec (код)
  

Выход:

 
<код класса>
сумма = 15
  

Обратите внимание, что тип возвращаемого значения функции компиляции — это объект code. Кроме того, здесь мы используем exec (), потому что исходная строка содержит несколько операторов python.Обратите внимание, что объект кода выполняется функцией exec (), и в консоли печатается «sum = 15».

Чтение кода из файла и компиляция

Допустим, у нас есть файл my_code. py со следующим содержанием.

 
х = 10
у = 20
print ('Умножение =', х * у)
  

Мы можем прочитать содержимое этого файла как строку, скомпилировать ее в объект кода и выполнить.

 
# чтение кода из файла
f = open ('my_code.py', 'г')
code_str = f.читать()
f.close ()
код = компиляция (code_str, 'my_code.py', 'exec')
exec (код)
  

Вывод: Умножение = 200

compile () с eval ()

Рассмотрим пример компиляции выражения Python в код и его выполнения с помощью функции eval ().

 
# пример eval
х = 5
код = компиляция ('x == 5', '', 'eval')
результат = eval (код)
печать (результат)

код = компиляция ('x + 5', '', 'eval')
результат = eval (код)
печать (результат)
  

Выход:

 
Правда
10
  

compile () с источником байтовой строки

Давайте посмотрим на пример использования байтовой строки в качестве источника.

 
bytes_str = байты ('x == 5', 'utf-8')
печать (тип (bytes_str))
код = компиляция (bytes_str, '', 'eval')
результат = eval (код)
печать (результат)
  

Выход:

 
<класс 'байты'>
Правда
  

compile () с объектом AST

Давайте посмотрим на пример использования объекта AST с функцией compile ().

 
импорт аст

ast_object = ast.parse ("print ('Привет, мир!')")
печать (тип (ast_object))
code = compile (ast_object, filename = "", mode = "exec")
печать (тип (код))
exec (код)
  

Выход:

 
<класс '_ast.Модуль '>
 

Сводка

Функция Python compile () позволяет нам создавать объект кода из строки, который впоследствии может быть выполнен с помощью функций exec () и eval (). Вам следует проявлять особую осторожность, если вы собираете вводимые пользователем данные, компилируете их в код и выполняете, потому что это может иметь нежелательные эффекты, например, выполнение команды rm -rf / .

Вы можете получить полный скрипт Python и другие примеры Python в нашем репозитории GitHub.

Ссылка: Официальная документация

Компиляция кода Python с помощью Cython

Эта статья была перенесена из моего блога https://blog.easyaspy.org/post/16/2019-05-15-compiling-python-code-with-cython

Если вы какое-то время занимались разработкой с использованием Python, возможно, вы слышали о Cython и о том, как он ускоряет работу. Cython - это оптимизирующий статический компилятор для языка программирования Python и языка программирования Cython, который является надмножеством Python. Cython преобразует ваш код Python в C, а затем создает / компилирует его с помощью компилятора C по вашему выбору.В мире Python это обычно называется Cythonizing . Прирост скорости велик, но все равно зависит от того, насколько оптимизирован ваш код Python.

Как цитировать код Python?

Первый шаг - получить доступный компилятор C в зависимости от платформы, которую мы используем, и версии Python, с которой вы работаете. Если мы разрабатываем под Linux, нам не нужно ничего устанавливать, так как большинство Linux-компьютеров поставляется с установленным компилятором GCC. Если в Windows есть рекомендуемый набор компиляторов для определенных версий Python, доступных здесь.

В этом руководстве мы будем использовать Python 3.7 в Windows 10. Самый простой и быстрый путь для нас - загрузить и установить Visual Studio Community 2019. Во время установки выберите Разработка настольных ПК с C ++ , нажмите Установить и вот и все! Вы будете загружать инструменты и SDK для разработки на C и C ++.

Следующим шагом является установка Cython с использованием pip .

  pip install cython  

Теперь мы можем начать работу над нашим модулем Python.Допустим, у нас есть файл Python с именем module.py , содержащий функцию hello () , и мы хотим его Cythonize.

  #! / Usr / bin / env python


def привет ():
    print ("Привет, мир!")
  

Первым шагом к Cythonizing является написание стандартного setuptools setup.py , содержащего определение для ext_modules . Мы просто передадим имя файла нашего модуля функции cythonize () . В setuptools наш cythonized модуль называется расширением.

  #! / Usr / bin / env python
из настройки импорта setuptools
из Cython. Build import cythonize

настроить(
    ext_modules = cythonize ('модуль.py')
)
  

Последний шаг - создать наше расширение, выполнив setup.py . Аргумент --inplace строит наше расширение в том же месте, что и module.py .

  python setup.py build_ext --inplace  

В итоге мы получим следующие файлы и каталоги. Каталог сборки содержит все файлы и объекты, используемые компилятором C.Для нас важны module.c , который является эквивалентом C нашего кода Python, и module.cp37-win_amd64.pyd , наше скомпилированное расширение.

  сборка /
module.c
module.cp37-win_amd64.pyd
module.py
setup.py  

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

  #! / Usr / bin / env python
из модуля импорт привет

если __name__ == '__main__':
    Здравствуйте()
  

Вывод:

  $ Пример Python. ру
Привет мир!  

Как Cythonize большие пакеты Python?

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

  #! / Usr / bin / env python
из настройки импорта setuptools
из Cython.Build import cythonize

настроить(
    ext_modules = cythonize ('амортизация / *. py')
)  

Причина этого в том, что __init__.py в пакетах не может быть скомпилирован, по крайней мере, обычными методами. Есть несколько хитрый способ сделать это, но я не буду его здесь обсуждать.

  ССЫЛКА: ошибка LNK2001: неразрешенный внешний символ PyInit___init__
build \ temp.win-amd64-3.7 \ Release \ amortization \ __ init __. cp37-win_amd64.lib: фатальная ошибка LNK1120: 1 неразрешенные внешние элементы
ошибка: команда 'C: \ Program Files (x86) \ Microsoft Visual Studio \ 2019 \ Community \ VC \ Tools \ MSVC \ 14. 20.27508 \ bin \ HostX86 \ x64 \ link .exe 'завершился ошибкой со статусом выхода 1120  

Чтобы решить эту проблему, нам нужно будет реорганизовать наш код и переместить коды из __init__.py . Нам нужно оставить этот файл пустым в пакете и не компилировать его.

  #! / Usr / bin / env python
из настройки импорта setuptools, Расширение

из Cython.Build import cythonize

ext_modules = cythonize ([
    Расширение ("amortization.amount", ["amortization / amount.py"]),
    Расширение ("amortization.schedule", ["amortization / schedule.py"]),
    Расширение ("amortization.amortize", ["amortization / amortize.py"]),
])

настроить(
    ext_modules = ext_modules
)
  

После запуска установки python.py build_ext --inplace, мы получим следующие файлы.

  __init__.py
amortize.c
amortize.cp37-win_amd64.pyd
amortize.py
amount.c
amount.cp37-win_amd64.pyd
amount.py
schedule.c
schedule.cp37-win_amd64.pyd
schedule.py  

Я временно удалил файлы . py , кроме __init__.py , и запустил pytest -v , чтобы убедиться, что код работает, хотя в этом нет необходимости, поскольку Python импортирует скомпилированные модули (.так в Unix и .pyd в Windows), если они доступны.

  tests / test_amortization.py :: test_amortization_amount ПРОЙДЕНО [50%]
tests / test_amortization.py :: test_amortization_schedule ПРОЙДЕНО [100%]

========================== 2 прошло за 0,05 секунды =================== ========  

Как распространять пакеты с поддержкой Cython на PyPI?

Просто запустив python setup.py bdist_wheel , вы получите двоичное колесо, которое можно использовать только на платформах с аналогичными версиями Python и платформами, как и у вас.Обратите внимание, что перед выполнением команды вам следует установить пакет wheel. Есть два способа поддержки всех платформ и версий:

  1. Создать бинарные колеса на всех целевых платформах и версиях и загрузить в PyPI
  2. Загрузить только исходный код в PyPI и позволить пользователю построить его

Первый вариант занимает много времени усилий, но мы можем автоматизировать процессы в конвейере CI / CD. Самый быстрый путь - это второй вариант, так как вам нужно только внести незначительные изменения в настройку .py .

  #! / Usr / bin / env python
из настройки импорта setuptools, Расширение

пытаться:
    из Cython.Build import cythonize

    ext_modules = cythonize ([
        Расширение ("amortization.amount", ["amortization / amount.py"]),
        Расширение ("amortization.schedule", ["amortization / schedule.py"]),
        Расширение ("amortization.amortize", ["amortization / amortize.py"]),
    ])
кроме ImportError:
    ext_modules = Нет

настроить(
    ext_modules = ext_modules
)
  

Чтобы собрать пакет только с исходным кодом, сначала удалите Cython и обязательно удалите все *.c и * .pyd файлы в модуле амортизации, затем запустите python setup.py sdist . Единственным недостатком этого варианта является то, что конечный пользователь должен установить cython и компилятор C. Попробуйте это, выполнив следующие шаги:

  # сначала установите компилятор C
pip install cython
pip install amortization -v # Добавьте -v, чтобы увидеть, что происходит за кулисами
  

Завершение

Cython увеличивает скорость модуля Python путем компиляции кода Python в C. Хотя это общий вариант использования Cython разработчиками, мы можем использовать его для обфускации кода. Если мы хотим защитить наш код от чужих глаз, мы определенно можем собрать его с помощью Cython и распространять без исходного кода.

10. Справочник по API - документация Python 3.7.2rc1

имя Название пакета строка
версия Номер версии
пакет; увидеть
distutils.версия
строка
описание Одна строка, описывающая
посылка
строка
long_description Подробное описание
посылка
строка
автор Имя автора пакета строка
email_ автора Электронный адрес
автор пакета
строка
Сопровождающий Имя текущего
сопровождающий, если отличается от
Автор. Обратите внимание, что если
предоставляется сопровождающий,
distutils будет использовать его как
автор в PKG-INFO
строка
supporter_email Электронный адрес
текущий сопровождающий, если
отличается от автора
строка
URL URL-адрес пакета.
(домашняя страница)
строка
download_url URL для загрузки пакета строка
упаковок Список пакетов Python, которые
distutils будет манипулировать
список строк
py_modules Список модулей Python, которые
distutils будет манипулировать
список строк
скрипты Список автономных скриптов.
файлы для сборки и
установлено
список строк
ext_modules Список расширений Python для
быть построенным
список экземпляров
distutils. core.Extension
классификаторы Список категорий для
посылка
список строк; действительные классификаторы перечислены в PyPI.
distclass Распределение
класс использовать
подкласс
distutils.core.Дистрибутив
имя_сценария Имя setup.py
скрипт - по умолчанию
систем.argv [0]
строка
script_args Аргументы к подаче
сценарий установки
список строк
варианты параметры по умолчанию для настройки
скрипт
словарь
лицензия Лицензия на пакет строка
ключевые слова Описательные метаданные, см.
PEP 314
список строк или разделенных запятыми

32. Пакет компилятора Python - документация Python v2.6.9

Не рекомендуется с версии 2.6: пакет компилятора был удален из Python 3.0.

Пакет компилятора Python - это инструмент для анализа исходного кода Python и
создание байт-кода Python. Компилятор содержит библиотеки для создания
абстрактное синтаксическое дерево из исходного кода Python и для генерации Python
байт-код из дерева.

Пакет компилятора - это источник Python в транслятор байт-кода, написанный на
Python.Он использует встроенный парсер и стандартный модуль парсера для
сгенерировал конкретное синтаксическое дерево. Это дерево используется для создания абстрактного
синтаксическое дерево (AST), а затем байт-код Python.

Полная функциональность пакета дублирует встроенный компилятор.
с интерпретатором Python. Он призван почти соответствовать его поведению
в яблочко. Зачем реализовывать другой компилятор, который делает то же самое? Посылка
полезен для множества целей. Его легче изменить, чем
встроенный компилятор. Генерируемый им AST полезен для анализа исходного кода Python.
код.

В этой главе объясняется, как различные компоненты пакета компилятора
Работа. Он совмещает справочный материал с учебным пособием.

32,1. Базовый интерфейс

Верхний уровень пакета определяет четыре функции. Если вы импортируете
компилятор, вы получите эти функции и набор модулей
содержится в упаковке.

compiler.parse ( buf )
Возвращает абстрактное синтаксическое дерево для исходного кода Python в buf
функция вызывает SyntaxError, если в исходном коде есть ошибка. В
возвращаемое значение - это экземпляр compiler.ast.Module, содержащий дерево.
compiler.parseFile ( путь )
Вернуть абстрактное синтаксическое дерево для исходного кода Python в указанном файле
по путь . Это эквивалентно parse (open (path) .read ()).
compiler.walk ( ast , посетитель [, verbose ])
Выполните предварительный просмотр абстрактного синтаксического дерева ast . Позвоните в соответствующий
для экземпляра посетителя для каждого обнаруженного узла.
compiler.compile ( source , filename , mode , flags = None , dont_inherit = None )

Скомпилируйте строку source , модуль, инструкцию или выражение Python в
объект кода, который может быть выполнен оператором exec или eval (). Этот
функция является заменой встроенной функции compile ().

Имя файла будет использоваться для сообщений об ошибках времени выполнения.

Режим должен быть «exec» для компиляции модуля, «single» для компиляции одиночного
(интерактивный) оператор или eval для компиляции выражения.

Флаги аргументы и dont_inherit влияют на будущие операторы, но
пока не поддерживаются.

compiler.compileFile ( исходный код )
Компилирует исходный файл и генерирует файл. pyc файл.

Пакет компилятора содержит следующие модули: ast,
consts, будущее, разное, pyassem, pycodegen,
символы, трансформер и посетитель.

32,2. Ограничения

Есть некоторые проблемы с проверкой ошибок в пакете компилятора. В
Интерпретатор обнаруживает синтаксические ошибки на двух разных этапах. Один набор ошибок
обнаруживается синтаксическим анализатором интерпретатора, второй - компилятором. В
пакет компилятора полагается на синтаксический анализатор интерпретатора, поэтому он получает первые фазы
проверки ошибок бесплатно.Он сам реализует вторую фазу, и это
реализация не завершена. Например, пакет компилятора не вызывает
ошибка, если имя встречается в списке аргументов более одного раза: def f (x, x):
...

Будущая версия компилятора должна исправить эти проблемы.

32,3. Абстрактный синтаксис Python

Модуль compiler.ast определяет абстрактный синтаксис для Python. в
абстрактное синтаксическое дерево, каждый узел представляет синтаксическую конструкцию. Корень
дерево - это объект Module.

Абстрактный синтаксис предлагает интерфейс более высокого уровня для синтаксического анализа исходного кода Python.
код. Модуль парсера и компилятор написаны на C для Python
интерпретатор использует конкретное синтаксическое дерево. Конкретный синтаксис тесно связан с
описание грамматики, используемое для парсера Python. Вместо одного узла
для конструкции часто бывает несколько уровней вложенных узлов, которые
введено правилами приоритета Python.

Абстрактное синтаксическое дерево создается модулем compiler.transformer.Преобразователь полагается на встроенный парсер Python для генерации конкретного
синтаксическое дерево. Он генерирует абстрактное синтаксическое дерево из конкретного дерева.

Модуль трансформатора был создан Грегом Штайном и Биллом Туттом для
экспериментальный компилятор Python-to-C. Текущая версия содержит ряд
модификации и улучшения, но основная форма абстрактного синтаксиса и
Трансформатор принадлежит Штайну и Тутту.

32.3.1. Узлы AST

Модуль compiler.ast создается из текстового файла, описывающего каждый
тип узла и его элементы.Каждый тип узла представлен как класс, который
наследуется от абстрактного базового класса compiler.ast.Node и определяет
набор именованных атрибутов для дочерних узлов.

класс compiler.ast.Node

Экземпляры узлов создаются автоматически генератором синтаксического анализатора.
Рекомендуемый интерфейс для конкретных экземпляров узла - использовать
общедоступные атрибуты для доступа к дочерним узлам. Открытый атрибут может быть привязан к
один узел или последовательность узлов, в зависимости от типа узла.За
Например, базовый атрибут узла Class привязан к
список узлов базового класса, а атрибут doc привязан к одному
узел.

У каждого экземпляра Node есть атрибут lineo, который может быть
Никто. ХХХ Не уверен, каковы правила, для каких узлов будет полезен
белье.

Все объекты Node предлагают следующие методы:

getChildren ()
Возвращает плоский список дочерних узлов и объектов в том порядке, в котором они
происходят. В частности, порядок узлов - это порядок, в котором они
появляются в грамматике Python.Не все дети являются узлами
экземпляры. Имена функций и классов, например, простые.
струны.
getChildNodes ()
Возвращает плоский список дочерних узлов в порядке их появления. Этот
метод похож на getChildren (), за исключением того, что он возвращает только те
дочерние элементы, являющиеся экземплярами Node.

Два примера иллюстрируют общую структуру классов узлов. В
В то время как оператор определяется следующей грамматической продукцией:

 while_stmt: "while" выражение ":" набор
               ["else" ":" люкс] 

Узел While имеет три атрибута: test, body и
else_.(Если естественное имя атрибута также является зарезервированным Python
слово, его нельзя использовать в качестве имени атрибута. Знак подчеркивания добавляется к
слово, чтобы сделать его допустимым идентификатором, поэтому else_ вместо
остальное.)

Оператор if более сложен, потому что он может включать несколько
тесты.

 if_stmt: 'if' test ':' suite ('elif' test ':' suite) * ['else' ':' suite] 

Узел If определяет только два атрибута: тесты и
else_. Атрибут tests - это последовательность тестового выражения,
последовательные пары тел.Для каждого if / elif есть одна пара
пункт. Первый элемент пары - это тестовое выражение. Второй
elements - это узел Stmt, содержащий код для выполнения, если тест
правда.

Метод getChildren () объекта If возвращает плоский список дочерних элементов.
узлы. Если есть три предложения if / elif и нет
else, тогда getChildren () вернет список из шести
элементы: первое тестовое выражение, первый Stmt, второй текст
выражение и др.

В следующей таблице перечислены подклассы узлов, определенные в
компилятор.ast и каждый из общедоступных атрибутов, доступных на их
экземпляры. Значения большинства атрибутов сами по себе являются Node
экземпляры или последовательности экземпляров. Когда значение отличается от
Например, тип указан в комментарии. Атрибуты перечислены в
порядок, в котором они возвращаются getChildren () и
getChildNodes ().

Тип узла Атрибут Значение
Добавить слева левый операнд
правый правый операнд
и узлов список операндов
AssAttr атрибут как цель
присвоение
выражение выражение слева
сторона точки
attrname имя атрибута, строка
флаги ХХХ
Ассистент узлов список элементов списка
назначен на
AssName название имя присваивается
флаги ХХХ
Задница узлов список элементов кортежа
назначен на
Утвердить тест тестируемое выражение
сбой стоимость
AssertionError
Назначить узлов список целей назначения,
один на знак равенства
выражение присвоенное значение
AugAssign узел
op
выражение
Обратное цитирование выражение
Bitand узлов
Битор узлов
Bitxor узлов
Перерыв
CallFunc узел выражение для вызываемого
аргументов список аргументов
star_args расширенное значение * -arg
dstar_args расширенный ** - значение аргумента
Класс название имя класса, строка
баз список базовых классов
doc строка документа, строка или
Нет
код тело оператора класса
Сравнить выражение
опс
Const значение
Продолжить
Декораторы узлов Список декораторов функций
выражения
Dict шт.
Исключить выражение
Див слева
правый
Эллипс
Выражение узел
Exec выражение
местные жители
глобальных
FloorDiv слева
правый
Для присвоить
список
кузов
else_
из имя мода
имен
Функция декораторов Декораторы или нет
название имя, используемое в def, строка
argnames список имен аргументов, как
струны
по умолчанию список значений по умолчанию
флаги ххх
doc строка документа, строка или
Нет
код тело функции
GenExpr код
GenExprFor присвоить
iter
IFS
GenExprIf тест
GenExprInner выражение
кв.
Getattr выражение
attrname
Глобальный имен
Если тестов
else_
Импорт имен
Инвертировать выражение
Ключевое слово название
выражение
Лямбда argnames
по умолчанию
флаги
код
Левое переключение передач слева
правый
Список узлов
ListComp выражение
кв
ListCompFor присвоить
список
IFS
ListCompIf тест
Мод слева
правый
Модуль doc строка документа, строка или
Нет
узел корпус модуля, а
Stmt
Мул слева
правый
Имя название
Не выражение
Или узлов
Пройдено
Мощность слева
правый
Печать узлов
dest
Printnl узлов
dest
Поднять expr1
expr2
expr3
Возврат значение
Правая передача слева
правый
Ломтик выражение
флаги
нижний
верх
Sliceobj узлов список выписок
Stmt узлов
Переходник слева
правый
Нижний индекс выражение
флаги
сабвуферов
TryExcept кузов
погрузчики
else_
ПопробоватьНаконец кузов
финал
Кортеж узлов
Унарный Добавить выражение
UnarySub выражение
В то время как тест
кузов
else_
С выражение
варс
кузов
Урожайность значение

32. 3.2. Узлы присвоения

Существует набор узлов, используемых для представления назначений. Каждое задание
в исходном коде становится единственным узлом Assign в AST.
Атрибут узлов - это список, содержащий узел для каждого назначения.
цель. Это необходимо, потому что присваивание может быть связано, например а = б =
2. Каждый узел в списке будет одним из следующих классов:
AssAttr, AssList, AssName или AssTuple.

Каждый целевой узел назначения будет описывать тип объекта, которому назначается:
AssName для простого имени, например.грамм. a = 1. AssAttr для
присвоенный атрибут, например a.x = 1. AssList и AssTuple для
список и расширение кортежа соответственно, например a, b, c = a_tuple.

Целевые узлы назначения также имеют атрибут flags, который указывает
используется ли узел для присвоения или в операторе удаления. В
AssName также используется для представления оператора удаления, например дель
Икс.

Если выражение содержит несколько ссылок на атрибут, присвоение или
Оператор delete будет содержать только один узел AssAttr - для последнего
ссылка на атрибут. Ссылки на другие атрибуты будут представлены как
Узлы Getattr в атрибуте expr объекта AssAttr
пример.

32.3.3. Примеры

В этом разделе показано несколько простых примеров AST для исходного кода Python. В
примеры демонстрируют, как использовать функцию parse (), как выглядит
Как выглядит AST, и как получить доступ к атрибутам узла AST.

Первый модуль определяет одну функцию. Предположим, он хранится в
/tmp/doublelib.py.

 "" "Это пример модуля.Это строка документации.
"" "

def double (x):
    "Вернуть дважды аргумент"
    вернуть x * 2
 

В сеансе интерактивного интерпретатора ниже я переформатировал длинный AST
репсов для удобочитаемости. Представители AST используют неквалифицированные имена классов. Если хочешь
чтобы создать экземпляр из repr, вы должны импортировать имена классов из
модуль compiler.ast.

 >>> компилятор импорта
>>> mod = compiler.parseFile ("/ tmp / doublelib.py")
>>> мод
Module ('Это пример модуля.\ n \ nЭто строка документации.  \ n ',
       Stmt ([Функция (None, 'double', ['x'], [], 0,
                      'Вернуть дважды аргумент',
                      Stmt ([Return (Mul ((Name ('x'), Const (2))))]))]))
>>> from compiler.ast import *
>>> Модуль ('Это пример модуля. \ N \ nЭто строка документации. \ N',
... Stmt ([Функция (None, 'double', ['x'], [], 0,
... 'Вернуть дважды аргумент',
... Stmt ([Return (Mul ((Name ('x'), Const (2))))]))]))
Module ('Это пример модуля.\ n \ nЭто строка документации. \ n ',
       Stmt ([Функция (None, 'double', ['x'], [], 0,
                      'Вернуть дважды аргумент',
                      Stmt ([Return (Mul ((Name ('x'), Const (2))))]))]))
>>> mod.doc
'Это пример модуля. \ N \ nЭто строка документации. \ N'
>>> для узла в mod.node.nodes:
... узел печати
...
Функция (None, 'double', ['x'], [], 0, 'Вернуть дважды аргумент',
         Stmt ([Return (Mul ((Name ('x'), Const (2))))]))
>>> func = mod.node.nodes [0]
>>> func.код
Stmt ([Return (Mul ((Name ('x'), Const (2))))])
 

32,4. Использование посетителей для прогулки AST

Шаблон посетителя ... Пакет компилятора использует вариант на
шаблон посетителя, который использует возможности интроспекции Python для
устраняют необходимость в большей части инфраструктуры посетителя.

Посещаемые классы не нужно программировать для приема посетителей. В
посетителю нужно только определить методы посещения для классов, которые он конкретно интересует
в; все остальное может обработать метод посещения по умолчанию.

XXX Волшебный метод visit () для посетителей.

compiler.visitor.walk ( дерево , посетитель [, подробный ])
класс компилятор. Посетитель. ASTVisitor

ASTVisitor несет ответственность за то, чтобы пройти по дереву в правильном
заказ. Прогулка начинается с вызова функции preorder (). Для каждого узла проверяется
аргумент посетитель функции preorder () для метода с именем «visitNodeType»
где NodeType - это имя класса узла, e.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *