强制字节码编译的Python实践?(.pyc)

4 投票
2 回答
1129 浏览
提问于 2025-04-16 23:00

我在研究Python解释器的时候,发现有些东西有编译后的对象文件(.pyc),而有些则没有,所以我有点搞不明白。

我找到了问题的答案,但现在又有点困惑。好吧,解释器会把脚本编译成一个模块……如果我理解得没错的话,这有点像C语言中的对象(我之前是C程序员,现在在学Python)——或者更像Java中的.class文件,因为它是编译后的字节码,而不是本地指令……总之,当你导入一个脚本,或者明确调用它进行编译时,解释器会这样做(不过后者似乎不太受欢迎)。

那么在这种理解下,编译后的字节码和未编译的字节码在运行时有什么区别呢?假设只有一个解释器(字节码解释器),这就意味着如果模块还没有编译,它必须在解释之前先进行语法分析、词法分析和解析(编译)。这样会不会导致执行时间更长呢?

如果你认为以上说法是对的,那么显然把模块编译成.pyc文件是最好的,而不是像标准的.py脚本那样实时运行。

这是否意味着在主运行中尽量减少执行时间是最好的选择呢?

我想,如果你的入口点有一些复杂的逻辑(比如我有几个树遍历和其他重比较),那么这个入口点本身是不是应该被封装起来,以便它能被编译呢?

也就是说,不是这样:

# file.py:
def main():
    <stuff goes here - setup, whatever shared resources different modules need, etc.>

main()

而是这样做会更好:

# wrapper.py:
from file.py import *
main()

希望我能清楚地表达我想问的问题。很可能我对Python中解释器/编译器的理解有误,这个问题可能根本不合理——毕竟我对Python还很陌生。

谢谢大家!

2 个回答

0

这是给初学者的内容,

在运行你的Python脚本之前,Python会自动把它编译成一种叫做字节码的代码。

运行脚本并不算是导入,所以不会生成.pyc文件。

举个例子,如果你有一个脚本文件abc.py,它导入了另一个模块xyz.py,当你运行abc.py时,xyz.pyc会被创建,因为xyz被导入了,但abc.pyc不会被创建,因为abc.py并没有被导入。

如果你需要为一个没有被导入的模块创建.pyc文件,可以使用py_compile和compileall模块。

py_compile模块可以手动编译任何模块。你可以在这个模块中使用py_compile.compile函数来进行交互式编译:

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

这样会把.pyc文件写到和abc.py相同的位置(你可以用可选参数cfile来覆盖这个位置)。

想了解更多,可以访问: http://effbot.org/pyfaq/how-do-i-create-a-pyc-file.htm

7

你说得对:

1) .pyc 文件是 Python 源代码编译成字节码的一个缓存副本。

2) 当你导入一个模块时,就会创建一个 .pyc 文件。

3) 你在 Python 命令行中指定的主程序不会被编译成 .pyc 文件。

4) 所以每次运行主程序时,它都会被重新编译。

但是:

主程序会被编译成字节码,然后这个字节码会被解释执行,所以实际上只有很小的额外开销(就是编译的时间),在主程序执行时并没有持续的额外开销。编译所需的时间与文件中的行数成正比,而不是与这些行被执行的次数成正比。

总结一下:别担心这个问题。

撰写回答