Если Python интерпретируется, что такое .pyc файлы?

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

Ответ 1

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

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

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

Ответ 2

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

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

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

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

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

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

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

Затем эти формы нижнего уровня выполняются соответствующими "виртуальными машинами", также известными как "интерпретаторы" - CPython VM, среда исполнения .Net, виртуальная машина Java (aka JVM), если это необходимо.

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

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

Ответ 3

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

Каждый язык может быть реализован либо интерпретатором, либо компилятором. Подавляющее большинство языков имеют по крайней мере одну реализацию каждого типа. (Например, есть интерпретаторы для 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, который затем интерпретируется.
  • Разгрузить Swallow: компилируется в байт-код CPython, который затем интерпретируется, пока не будет идентифицирован путь горячего кода, который затем компилируется в IR LLVM, который компилятор LLVM затем компилирует в собственный машинный код.
  • Cython: компилирует код Python в переносимый код C, который затем компилируется стандартным компилятором C
  • Nuitka: компилирует код Python в машинно-зависимый код C++, который затем компилируется стандартным компилятором C

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

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

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

Ответ 4

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

Ответ 5

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

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

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

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

введите описание изображения здесь

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

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

Ответ 6

ЭТО ДЛЯ НАЧИННИКОВ,

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

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

Например, если у вас есть файл abc.py скрипт, который импортирует другой модуль xyz.py, при запуске abc.py, xyz.pyc будет создан, так как хуг импортируется, но не abc.pyc файл не будет создан, поскольку аЬс. 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

Ответ 7

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

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

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

Ответ 8

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

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

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

После создания *.pyc файла нет необходимости *.py файла, если вы его не отредактируете.

Ответ 9

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

Ответ 10

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

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

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

Если вам нужно создать файл .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.

Если вам интересно, вы можете посмотреть байт-код с помощью модуля dis:

>>> def hello():
...     print "hello!"
...
>>> dis.dis(hello)
  2           0 LOAD_CONST               1 ('hello!')
              3 PRINT_ITEM
              4 PRINT_NEWLINE
              5 LOAD_CONST               0 (None)
              8 RETURN_VALUE