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

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

9 ответов


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

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

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


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

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

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

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

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

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

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

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

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


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

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

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

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

  • IronPython: компилируется в деревья DLR, которые затем DLR компилируется в байт-код CIL. Что происходит с байт-кодом CIL, зависит от того, на каком CLI вы работаете, но 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, который затем интерпретируется, пока не идентифицирует пути горячего кода,которые затем компилируются в LLVM IR, который компилятор LLVM затем компилируется в машинный код.

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

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

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


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


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

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

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

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

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

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

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

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

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

python -m compileall

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


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

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

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

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

enter image description here

дополнительные сведения:

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


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

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

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


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

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

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

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


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