我已经了解了Python是一种解释的语言...但是,当我查看我的Python源代码时,我会看到 .pyc 文件,Windows将其标识为“编译Python文件”。这些进来了?

有帮助吗?

解决方案

他们包含 字节代码, ,这就是Python解释器将源汇编成的内容。然后,该代码由Python的虚拟机执行。

Python的文档解释了这样的定义:

Python是一种解释的语言,而不是编译的语言,尽管由于字节码编译器的存在,这种区别可能模糊。这意味着可以直接运行源文件,而无需明确创建可执行文件,然后运行。

其他提示

我被赋予理解Python是一种解释的语言...

这个受欢迎的模因是不正确的,或者是基于对(自然)语言层面的误解:类似的错误是说“圣经是一本精装书”。让我解释一下这个比喻...

“圣经”是“一本书” 班级 (实际的物理对象);这些书被认为是“圣经的副本”的书籍应该具有基本的共同点(尽管内容,但即使这些内容也可以使用不同的语言,具有不同的可接受翻译,脚注水平和其他注释) - 但是,这些书籍是完全允许在无数方面有所不同 不是 被认为是基本的 - 绑定,绑定的颜色,印刷中使用的字体,插图,如果有的话,是否宽阔的可写边缘,数字和类型的内置书签等等等等等等。

很有可能 典型的 圣经的印刷确实将具有精装绑定 - 毕竟,这本书通常是要一遍又一遍地阅读,在几个地方添加书签,通过寻找给定的章节和换句话,等等,等等,等等。良好的精装绑定可以使给定的副本在这种使用下持续更长的时间。但是,这些是平凡的(实用)问题,无法用来确定给定的实际书籍对象是否是圣经的副本:平装打印是完全可能的!

同样,在定义一类的意义上,Python是一种“语言” 实施 这在某些基本方面必须相似(语法,大多数语义,除了明确允许的部分外,但几乎完全允许它们的几乎所有“实施”细节,包括它们如何处理它们给出的源文件,无论是将源编译到某些较低级别的表格(以及如果是哪种表格) - 以及是否保存此类编译表格,磁盘或其他地方),如何执行上述表格,等等。

古典实施CPYTHON通常被称为“ Python”,但它只是几种生产质量的实现之一,与Microsoft的Ironpython并肩作用(将CLR代码汇编为CLR代码,IE,.NET”),Jython (将其编译为JVM代码),PYPY(用Python本身编写,可以编译为各种“后端”表单,包括“ Just-Ond-Um-time”生成的机器语言)。它们都是Python(==“ Python语言的实现”),就像许多表面上不同的书籍对象都可以是圣经(==“圣经的副本”)。

如果您对CPYTHON感兴趣:它将源文件编译为Python特定的下层表单(称为“字节”),则在需要时自动执行此操作(当没有对应于源文件或对应的biontecode文件时字节码文件比源古老或由不同的Python版本编译),通常将字节码文件保存到磁盘上(以后避免重新编译它们)。 Otoh Ironpython通常会编译为CLR代码(是否将其保存到磁盘上,取决于磁盘),将Jython和Jython汇编为JVM代码(是否将其保存到磁盘上 - 它将使用 .class 扩展名如果保存它们)。

然后,这些较低级别的表格由适当的“虚拟机”执行,也称为“解释器” - CPYTHON VM,.NET运行时,Java VM(又称JVM),可根据适当的方式执行。

因此,从且仅当C#和Java为:所有这些都有典型的实现策略,即首先生产字节码,然后通过VM/Instrupter执行,Python是一种“解释性语言”,仅当C#和Java是一种“解释语言”。 。

更有可能的重点是汇编过程如何“沉重”,缓慢和高级仪式。 Cpython的设计旨在尽可能快地进行编译,尽可能轻巧,仪式很少 - 编译器进行错误检查和优化的少量,因此它可以快速运行,少量存储在需要时自动透明地运行,无需用户即使在大多数情况下都需要意识到正在进行汇编。 Java和C#通常在编译过程中接受更多工作(因此不执行自动汇编),以便更彻底地检查错误并进行更多优化。这是一个连续的灰色鳞片,而不是黑色或白色的情况,在某种程度上放置阈值并说只有超过该水平,您将其称为“汇编”! - )

没有解释的语言。解释器或编译器是否使用纯粹是 执行 并且与该语言无关。

每一个 语言可以由解释器或编译器实施。绝大多数语言至少具有每种类型的一种实现。 (例如,有针对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 Sourcecode,直到标识热代码路径为止,然后将其编译为JVML字节码。 JVML字节码发生的事情取决于您正在运行的JVM。 Maxine将直接将其编译为未优化的本机代码,直到它标识热代码路径为止,然后将其重新编译为优化的本机代码。热点将首先解释JVML字节码,然后最终将热代码路径编译为优化的机器代码。
  • PYPY:编译到PYPY字节码,然后由pypy VM解释,直到它标识然后根据您在哪个平台上运行的平台来识别然后将其编译为本机代码,JVML字节码或CIL字节码。
  • CPYTHON:将其解释为cpython bytecode,然后解释。
  • 无固定的Python:将其解释为CPYTHON字节码,然后将其解释。
  • Unladen Swallow:将其编译到CPYTHON字节码,然后将其解释为直到标识热代码路径,然后将其编译为LLVM IR,然后将其编译为LLVM编译器,然后将其编译为本机机器代码。
  • Cython:将Python代码编译到便携式C代码,然后将其编译为标准C编译器
  • Nuitka:将Python代码编译到机器依赖性的C ++代码,然后使用标准C编译器编译

您可能会注意到,该列表中的每个实施方式(加上我没有提及的其他一些,例如Tinypy,Shedskin或Psyco)都有一个编译器。实际上,据我所知,目前没有纯粹解释的Python实施,没有计划实施此类实施,也从未实施过这样的实施。

“解释语言”一词不仅没有意义,即使您将其解释为“具有解释实现的语言”,这显然是不正确的。谁告诉你,显然不知道他在说什么。

特别是 .pyc 您看到的文件是由CPYTHON,无固定Python或Unladen吞咽产生的缓存字节码文件。

这些是由Python解释器创建的 .py 文件已导入,它们包含导入模块/程序的“编译字节码”,其想法是可以在随后的后续中跳过从源代码到bytecode的“翻译”(仅需要一次) import如果是 .pyc 比相应的 .py 文件,从而稍微超速启动。但这仍然是解释的。

为了加快加载模块的速度,Python缓存了.pyc中模块的编译内容。

CPYTHON将其源代码编译到“字节代码”中,出于性能原因,只要源文件更改,它就会在文件系统上缓存此字节代码。这使得Python模块的加载速度更快,因为可以绕过编译阶段。当您的源文件为foo.py时,cpython将在源旁边的foo.pyc文件中缓存字节代码。

在Python3中,Python的Import Machinery被扩展,以在每个Python软件包目录中的单个目录中编写和搜索字节代码缓存文件。该目录将称为__pycache__。

这是一个流程图,描述了如何加载模块:

enter image description here

了解更多信息:

参考:PEP3147
参考:“编译” Python文件

这是给初学者的

Python在运行之前,将您的脚本自动编译为编译脚本,即所谓的字节代码。

运行脚本不被视为导入,不会创建.pyc。

例如,如果您有脚本文件 abc.py 导入另一个模块 xyz.py, ,当你跑步时 abc.py, xyz.pyc 由于XYZ是导入的,但不会创建ABC.PYC文件 创建 由于没有进口ABC.Py。

如果您需要为未导入的模块创建.pyc文件,则可以使用 py_compilecompileall 模块。

py_compile 模块可以手动编译任何模块。一种方法是使用 py_compile.compile 在该模块中函数互动:

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

这将将.pyc写入与abc.py相同的位置(您可以使用可选参数覆盖该位置 cfile).

您还可以使用CompileAll模块自动编译目录中的所有文件。

python -m compileall

如果省略了目录名称(本示例中的当前目录),则该模块编译了在 sys.path

Python(至少是最常见的实现)遵循将原始源编译为字节代码的模式,然后解释虚拟机上的字节代码。这意味着(同样,最常见的实现)既不是纯解释器也不是纯编译器。

但是,另一侧是汇编过程大多是隐藏的 - .pyc文件基本上被视为缓存;他们加快了速度,但是通常您不必意识到它们。它会根据文件时间/日期邮票在必要时自动无效并重载它们(重新编译源代码)。

我唯一看到这个问题的唯一问题是,当一个汇编的字节码文件以某种方式获得了时间戳,这意味着它总是比源文件更新。由于看起来更新,因此源文件从未重新编译,因此无论您做出了什么变化,它们都被忽略了...

Python的 *.py文件只是您编写一些代码行的文本文件。当您尝试使用“ python filename.py”执行此文件时

此命令调用Python虚拟机。 Python虚拟机具有2个组件:“编译器”和“解释器”。解释器无法直接读取 *.py文件中的文本,因此此文本首先转换为针对PVM的字节代码 (不是硬件,而是PVM). 。 PVM执行此字节代码。 *也生成.pyc文件,作为运行它的一部分,该文件会在shell或其他文件中执行您的导入操作。

如果已经生成此 *.pyc文件,那么下次您下次运行/执行 *.py文件时,系统直接加载您的 *.pyc文件,该文件不需要任何汇编(这将为您节省一些处理器的机器周期)。

一旦生成 *.pyc文件,除非您进行编辑,否则就不需要 *.py文件。

Python代码经历了2个阶段。第一步将代码编译到.pyc文件中,该文件实际上是一个字节。然后,使用CPYTHON解释器解释了此.PYC文件(字节码)。请参阅 这个 关联。这里可以简单地解释代码编译和执行过程。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top