强制字节码编译的Python实践?(.pyc)
我在研究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 个回答
这是给初学者的内容,
在运行你的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
你说得对:
1) .pyc 文件是 Python 源代码编译成字节码的一个缓存副本。
2) 当你导入一个模块时,就会创建一个 .pyc 文件。
3) 你在 Python 命令行中指定的主程序不会被编译成 .pyc 文件。
4) 所以每次运行主程序时,它都会被重新编译。
但是:
主程序会被编译成字节码,然后这个字节码会被解释执行,所以实际上只有很小的额外开销(就是编译的时间),在主程序执行时并没有持续的额外开销。编译所需的时间与文件中的行数成正比,而不是与这些行被执行的次数成正比。
总结一下:别担心这个问题。