为什么主要的可运行Python脚本没有编译成模块这样的pyc文件?

Why are main runnable Python scripts not compiled to pyc files like modules?

我知道当你导入一个模块时,这个文件被编译成一个.pyc文件来加快速度?为什么主文件也没有编译为.pyc?这会减慢速度吗?那么,最好将主文件尽可能小,还是无关紧要?


加载模块时,py文件被"字节编译"为pyc文件。时间戳记录在PYC文件中。这样做不是为了让它运行得更快,而是为了更快地加载。因此,在加载模块时"字节编译"模块是有意义的。

  • http://docs.python.org/tutorial/modules.html编译的python文件

[编辑:包括注释、参考文献]

From PEP 3147 on"Byte code
compilation":

cpython将其源代码编译为"字节代码",出于性能原因,每当源文件发生更改时,它就会在文件系统上缓存该字节代码。这使得加载python模块更快,因为编译阶段可以绕过。当源文件是foo.py时,cpython缓存字节源文件旁边的foo.pyc文件中的代码。

How byte code compiled files are
tracked with respect to Python version
and"py" file changes:

它还将在编译的字节代码".pyc"文件中插入一个幻数。每当Python更改字节代码格式时,通常在主要版本中都会发生这种变化。这样可以确保为以前版本的虚拟机构建的pyc文件不会导致问题。时间戳用于确保pyc文件与用于创建它。当幻数或时间戳不匹配时,重新编译py文件并写入新的pyc文件。

"pyc"文件在Python主要版本中不兼容。当python找到pyc时文件具有不匹配的幻数,它返回到较慢的进程重新编译源。

这就是原因,如果您只是简单地分发为同一平台编译的".pyc"文件,那么在Python版本发生更改时,这些文件将不再工作。

In Nutshell

如果有一个字节编译的文件".pyc",并且它的时间戳指示它是最近的,那么它将被加载,否则,Python将回退加载".py"文件的较慢方法。".py"文件的执行性能不受影响,但加载".pyc"文件的速度比".py"文件快。

考虑执行导入b.py的a.py

1
2
3
4
5
6
Typical total performance = loading time (A.py) + execution time (A.py) +
                            loading time (B.py) + execution time (B.py)

Since loading time (B.pyc)  <  loading time (B.py)

You should see a better performance by using the byte compiled"pyc" files.

也就是说,如果您有一个大的脚本文件x.py,那么模块化它,并将内容移动到其他模块,这会降低字节代码编译文件的加载时间。

另一个推论是,模块往往比脚本或主文件更稳定。因此,它根本就不是字节编译的。

References

  • http://effbot.org/zone/python-compile.htm网站
  • http://www.network-theory.co.uk/docs/pytut/compiledpythonfiles.html


编译主脚本对于诸如/usr/bin中的脚本来说是很烦人的。.pyc文件在同一目录中生成,从而污染公共位置。