为什么主要可运行的Python脚本没有像模块一样编译成pyc文件? [重复]

问题描述 投票:0回答:2

我知道当您导入模块时,该文件会被编译成

.pyc
文件以使其更快?为什么主文件也没有编译成
.pyc
?这会减慢速度吗?那么主文件越小越好,或者没关系?

python
2个回答
36
投票

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

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

来自“字节码编译”的 PEP 3147:

CPython 将其源代码编译为“字节代码”,出于性能原因, 每当源文件发生更改时,它都会将此字节代码缓存在文件系统上。 这使得 Python 模块的加载速度更快,因为编译阶段 可以被绕过。当你的源文件是

foo.py
时,CPython 会缓存该字节 代码位于源代码旁边的
foo.pyc
文件中。

字节码编译文件是怎样的 根据 Python 版本进行跟踪 和“py”文件更改:

它还在编译后的字节码“.pyc”文件中插入一个幻数。

只要 Python 更改字节码格式(通常是在主要版本中),这种情况就会发生变化。
这可确保为以前版本的 VM 构建的 pyc 文件不会导致问题。 时间戳用于确保 pyc 文件与之前的 py 文件匹配 用于创建它。当幻数或时间戳不匹配时, 重新编译py文件并写入新的pyc文件。

“pyc”文件在 Python 主要版本之间不兼容。当Python找到pyc时 文件具有不匹配的幻数,它会退回到重新编译源代码的较慢过程。

这就是原因,如果你简单地分发为同一平台编译的“.pyc”文件,如果Python版本发生变化,将不再起作用。

简而言之

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

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

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,将其模块化并将内容移动到其他模块会导致字节码编译文件的加载时间缩短。

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

参考文献

0
投票

对于例如以下脚本中的脚本来说,编译主脚本会很烦人。

/usr/bin
。 .pyc 文件在同一目录中生成,从而污染了公共位置。

© www.soinside.com 2019 - 2024. All rights reserved.