Python是一种解释性语言。但是为什么我的源目录包含。pyc文件,这些文件被Windows识别为“编译过的Python文件”?


当前回答

它们是由Python解释器在导入.py文件时创建的,它们包含导入模块/程序的“已编译字节码”,其思想是,如果.pyc比相应的.py文件更新,则可以在后续导入时跳过从源代码到字节码的“翻译”(只需完成一次),从而略微加快启动速度。但它仍然是被解释的。

其他回答

Python代码经过两个阶段。第一步将代码编译成.pyc文件,这实际上是一个字节码。然后使用CPython解释器解释这个.pyc文件(字节码)。请参考此连结。这里用简单的术语解释了代码编译和执行的过程。

它们是由Python解释器在导入.py文件时创建的,它们包含导入模块/程序的“已编译字节码”,其思想是,如果.pyc比相应的.py文件更新,则可以在后续导入时跳过从源代码到字节码的“翻译”(只需完成一次),从而略微加快启动速度。但它仍然是被解释的。

语言规范与语言实现的重要区别是:

语言规范只是带有语言正式规范的文档,具有上下文无关的语法和语义规则定义(如指定基本类型和作用域动态)。 语言实现只是一个程序(编译器),它根据语言的规范实现语言的使用。

Any compiler consists of two independent parts: a frontend and backend. The frontend receives the source code, validate it and translate it into an intermediate code. After that, a backend translate it to machine code to run in a physical or a virtual machine. An interpreter is a compiler, but in this case it can produce a way of executing the intermediate code directly in a virtual machine. To execute python code, its necessary transform the code in a intermediate code, after that the code is then "assembled" as bytecode that can be stored in a file.pyc, so no need to compile modules of a program every time you run it. You can view this assembled python code using:

from dis import dis
def a(): pass

dis(a)

任何人都可以用Python语言构建静态二进制的编译器,就像可以构建C语言的解释器一样。有一些工具(lex/yacc)可以简化编译器的构建过程并使之自动化。

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

然而,另一方面,编译过程基本上是隐藏的——.pyc文件基本上被视为缓存;它们能加快速度,但你通常根本不需要注意到它们。它在必要时根据文件时间/日期戳自动使它们失效并重新加载(重新编译源代码)。

我所见过的唯一一次问题是,编译后的字节码文件以某种方式获得了未来的时间戳,这意味着它看起来总是比源文件更新。因为它看起来更新,源文件从来没有重新编译过,所以无论你做了什么更改,它们都被忽略了…

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

CPython将源代码编译为“字节码”,出于性能考虑,当源文件发生更改时,CPython会将此字节码缓存到文件系统中。这使得Python模块的加载速度更快,因为可以绕过编译阶段。当你的源文件是foo.py时,CPython将字节代码缓存在foo.py文件中。Pyc文件就在源代码旁边。

在python3中,Python的导入机制被扩展为在每个Python包目录中的单个目录中写入和搜索字节码缓存文件。这个目录将被称为__pycache__。

下面是一个描述如何加载模块的流程图:

欲了解更多信息:

裁判:PEP3147 参考:“编译”的Python文件