Если Python интерпретируется, что такое файлы .pyc? - PullRequest
959 голосов
/ 08 июня 2010

Мне дали понять, что Python является интерпретируемым языком ... Однако, когда я смотрю на свой исходный код Python, я вижу .pyc файлы, которые Windows определяет как «Скомпилированные файлы Python». Куда они приходят?

Ответы [ 9 ]

915 голосов
/ 08 июня 2010

Мне дали понять, что Python является интерпретируемым языком ...

Этот популярный мем некорректен или, скорее, построен на неправильном понимании (естественного) языкаУровни: похожая ошибка - сказать: «Библия - книга в твердом переплете».Позвольте мне объяснить это сравнение ...

"Библия" - это "книга" в том смысле, что она является классом (реальных физических объектов, идентифицированных как) книг;Предполагается, что книги, обозначенные как «копии Библии», имеют нечто общее (содержание, хотя даже они могут быть на разных языках, с разными приемлемыми переводами, уровнями сносок и другими аннотациями), однако эти книгивполне допустимо отличаться множеством аспектов, которые не считаются фундаментальными - вид переплета, цвет переплета, шрифт (ы), используемые при печати, иллюстрации, если таковые имеются, широкие поля для записи или нет,числа и виды встроенных закладок и т. д. и т. п.

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

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

Классическая реализация, CPython, часто для краткости называется просто «Python» - но это всего лишь одиннескольких реализаций качества производства, наряду с IronP от Microsoftython (который компилируется в коды CLR, т. е. ".NET"), Jython (который компилируется в коды JVM), PyPy (который написан на самом Python и может компилироваться в огромное разнообразие "внутренних" форм, включая "простосвоевременно созданный машинный язык).Все они - Python (== "реализации языка Python"), точно так же, как многие поверхностно разные книжные объекты могут быть Библиями (== "копии Библии").

Если вы заинтересованы вВ частности, CPython: он компилирует исходные файлы в специфичную для Python форму нижнего уровня (известную как «байт-код»), делает это автоматически при необходимости (когда нет файла байт-кода, соответствующего исходному файлу, или файл байт-кода старше, чемисходный код или скомпилированный другой версией Python), обычно сохраняет файлы байт-кода на диск (чтобы избежать их повторной компиляции в будущем).OTOH IronPython обычно компилируется в коды CLR (сохраняя их на диск или нет, в зависимости от ситуации) и Jython в коды JVM (сохраняя их на диск или нет - он будет использовать расширение .class, если сохранит их).

Эти формы более низкого уровня затем выполняются соответствующими «виртуальными машинами», также известными как «интерпретаторы» - виртуальная машина CPython, среда выполнения .Net, виртуальная машина Java (также известная как JVM).

Таким образом, в этом смысле (что делают типичные реализации), Python является «интерпретируемым языком» тогда и только тогда, когда есть C # и Java: у всех них есть типичная стратегия реализации - сначала генерировать байт-код, а затем выполнять его через VM / интерпретатор..

Скорее всего, основное внимание уделяется тому, насколько «тяжелым», медленным и запоминающимся является процесс компиляции. CPython предназначен для компиляции настолько быстро, насколько это возможно, настолько легко, насколько это возможно, с минимально возможной церемонией - компилятор выполняет очень мало проверки и оптимизации ошибок, поэтому он может работать быстро и с небольшими объемами памяти, что, в свою очередь, позволяет ему запускаться автоматически и прозрачно при необходимости, даже если пользователю не нужно знать, что в большинстве случаев происходит компиляция. Java и C # обычно принимают больше работы во время компиляции (и поэтому не выполняют автоматическую компиляцию), чтобы более тщательно проверять ошибки и выполнять больше оптимизаций. Это континуум серых шкал, а не черно-белая ситуация, и было бы совершенно произвольно установить порог на каком-то заданном уровне и сказать, что только выше этого уровня вы называете это «компиляцией»! -)

600 голосов
/ 08 июня 2010

Они содержат байтовый код , к которому интерпретатор Python компилирует исходный код.Этот код затем выполняется виртуальной машиной Python.

Документация Python объясняет это определение следующим образом:

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

147 голосов
/ 08 июня 2010

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

Каждый язык может быть реализованлибо интерпретатор, либо компилятор.Подавляющее большинство языков имеют по крайней мере одну реализацию каждого типа.(Например, существуют интерпретаторы для C и C ++, а также есть компиляторы для JavaScript, PHP, Perl, Python и Ruby.) Кроме того, большинство современных реализаций языка фактически комбинируют как интерпретатор, так и компилятор (или даже несколько компиляторов).

Язык - это просто набор абстрактных математических правил.Интерпретатор - это одна из нескольких конкретных стратегий реализации языка.Эти двое живут на совершенно разных уровнях абстракции.Если бы английский был типизированным языком, термин «интерпретируемый язык» был бы ошибкой типа.Утверждение «Python - это интерпретируемый язык» - это не просто ложь (поскольку ложь подразумевает, что это утверждение имеет смысл, даже если оно неверно), оно просто не имеет смысла смысла , потому чтоязык никогда не может быть определен как "интерпретируемый".

В частности, если вы посмотрите на существующие в настоящее время реализации Python, это стратегии реализации, которые они используют:

  • IronPython: компилируется в деревья DLR, которые затем DLR компилирует в байт-код CIL.Что происходит с байт-кодом CIL, зависит от того, на каком CLI VES вы работаете, но Microsoft .NET, GNU Portable.NET и Novell Mono в конечном итоге скомпилируют его в машинный код.
  • Jython: интерпретирует исходный код Python до тех пор, пока он не будетопределяет пути горячего кода, которые затем компилируются в байт-код JVML.Что происходит с байт-кодом JVML, зависит от того, на какой JVM вы работаете.Maxine напрямую скомпилирует его в неоптимизированный нативный код, пока не определит пути горячего кода, которые затем перекомпилирует в оптимизированный нативный код.HotSpot сначала интерпретирует байт-код JVML, а затем в конечном итоге компилирует пути горячего кода в оптимизированный машинный код.
  • PyPy: компилируется в байт-код PyPy, который затем интерпретируется виртуальной машиной PyPy до тех пор, пока он не определит пути горячего кода, которые онзатем компилируется в собственный код, байт-код JVML или байт-код CIL, в зависимости от того, на какой платформе вы работаете.
  • CPython: компилируется в байт-код CPython, который затем интерпретируется.
  • Stackless Python: компилируется в байт-код CPythonкоторый затем интерпретирует.
  • Unladen Swallow: компилирует в байт-код CPython, который затем интерпретирует, пока не идентифицирует пути горячего кода, которые затем компилируется в IR LLVM, который компилятор LLVM затем компилирует в собственный машинный код.

Вы можете заметить, что у каждой из реализаций в этом списке (плюс некоторые другие, которые я не упомянул, такие как tinypy, Shedskin или Psyco) есть компилятор.На самом деле, насколько я знаю, в настоящее время не существует реализации Python, которая является чисто интерпретируемой, такая реализация не планируется и такой реализации никогда не было.

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

В частности, файлы .pyc, которые вы видите, являются кэшированными файлами байт-кода, созданными CPython, Stackless Python или Unladen Swallow.

59 голосов
/ 08 июня 2010

Они создаются интерпретатором Python при импорте файла .py и содержат «скомпилированный байт-код» импортированного модуля / программы, идея заключается в том, что «перевод» из исходного кода в байт-код (который тольконеобходимо выполнить один раз) можно пропустить на последующих import с, если .pyc новее соответствующего файла .py, что немного ускоряет запуск.Но это все еще интерпретируется.

36 голосов
/ 11 июля 2017

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

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

В python3 механизм импорта Python расширен для записи и поиска файлов кэша байт-кода в одном каталоге внутри каждого каталога пакета Python. Этот каталог будет называться __pycache__.

Вот блок-схема, описывающая, как загружаются модули:

enter image description here

Для получения дополнительной информации:

исй: PEP3147
ref: «Скомпилированные» файлы Python

35 голосов
/ 03 ноября 2016

ЭТО ДЛЯ НАЧИНАЮЩИХ,

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

Запуск скрипта не считается импортом, и .pyc не будет создан.

Например, если у вас есть файл сценария abc.py , который импортирует другой модуль xyz.py , при запуске abc.py , xyz.pyc будет создан после импорта xyz, но файл abc.pyc не будет создан , поскольку abc.py не импортируется.

Если вам нужно создать файл .pyc для модуля, который не импортируется, вы можете использовать модули py_compile и compileall.

Модуль py_compile может вручную скомпилировать любой модуль. Одним из способов является интерактивное использование функции py_compile.compile в этом модуле:

>>> import py_compile
>>> py_compile.compile('abc.py')

Это запишет .pyc в то же место, что и abc.py (вы можете переопределить его с помощью необязательного параметра cfile).

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

python -m compileall

Если имя каталога (текущий каталог в этом примере) опущено, модуль компилирует все найденное на sys.path

20 голосов
/ 08 июня 2010

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

Другая сторона этого, однако, в том, что процесс компиляции в основном скрыт - файлы .pyc в основном обрабатываются как кеш; они ускоряют процесс, но обычно вам не нужно о них вообще знать. Он автоматически делает недействительными и перезагружает их (перекомпилирует исходный код), когда это необходимо, на основании отметок времени / даты файла.

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

12 голосов
/ 15 декабря 2015

Файл Python * .py - это просто текстовый файл, в котором вы пишете несколько строк кода.Когда вы пытаетесь выполнить этот файл, используя «python filename.py»

Эта команда вызывает виртуальную машину Python.Виртуальная машина Python имеет 2 компонента: «компилятор» и «интерпретатор».Интерпретатор не может непосредственно прочитать текст в файле * .py, поэтому этот текст сначала преобразуется в байтовый код, предназначенный для PVM (не аппаратного, а PVM) .PVM выполняет этот байт-код.Файл * .pyc также генерируется как часть его запуска, который выполняет операцию импорта для файла в оболочке или в каком-либо другом файле.

Если этот файл * .pyc уже создан, то каждый раз при следующем запуске /запустите ваш файл * .py, система напрямую загрузит ваш файл * .pyc, который не нужно будет компилировать (это сэкономит вам некоторые машинные циклы процессора).* .py файл не нужен, если вы его не редактируете.

7 голосов
/ 26 марта 2015

Python-код проходит 2 этапа. Первый шаг компилирует код в файлы .pyc, который на самом деле является байт-кодом. Затем этот файл .pyc (байт-код) интерпретируется с использованием интерпретатора CPython. Пожалуйста, обратитесь к этой ссылке. Здесь процесс компиляции и выполнения кода объясняется в простых терминах.

...