为什么编译Python代码?

为什么要编译Python脚本?您可以直接从.py文件运行它们,它工作得很好,那么是否有性能优势或其他什么?

我还注意到我的应用程序中的一些文件被编译成.pyc,而其他文件则没有,这是为什么?

229562 次浏览

在运行编译脚本时,肯定会有性能差异。如果你运行普通的.py脚本,机器会在每次运行时编译它,这需要时间。在现代机器上,这几乎不明显,但随着脚本的增长,这可能会成为一个更大的问题。

运行编译过的python时性能有所提高。然而,当你将.py文件作为导入模块运行时,python将编译并存储它,只要.py文件没有改变,它将始终使用编译后的版本。

使用任何可解释的语言,当文件被使用时,过程看起来像这样:
1. 文件由interpeter处理。< Br / > 2. 文件被编译
3.执行已编译的代码。
< / p >

显然,通过使用预编译代码,你可以省去第2步,这适用于python, PHP和其他。

这里有一篇有趣的博客文章解释了它们的区别 这里有一个条目解释了Python编译过程http://effbot.org/zone/python-compile.htm

是的,性能是主要原因,据我所知,也是唯一的原因。

如果您的一些文件没有被编译,可能是因为目录权限或其他原因,Python无法写入.pyc文件。或者可能未编译的文件从来没有被加载……(脚本/模块只有在第一次加载时才会被编译)

它被编译成字节码,使用起来非常非常快。

有些文件没有被编译的原因是,每次运行脚本时,你用python main.py调用的主脚本都会被重新编译。所有导入的脚本都将被编译并存储在磁盘上。

Ben Blank:

值得注意的是,当运行一个 编译脚本具有更快的启动 时间(因为它不需要时间 编译),它没有运行任何 更快。< / p >

如前所述,将python代码编译为字节码可以提高性能。这通常由python本身处理,仅用于导入脚本。

编译python代码的另一个原因可能是为了保护你的知识产权不被复制和/或修改。

你可以在Python文档中阅读更多有关此的内容。

.pyc文件是已经编译为字节码的Python。如果Python发现一个.pyc文件与你调用的.py文件同名,它会自动运行一个.pyc文件。

“Python简介”这是关于编译的Python文件:

当 它是从a '读过来的。Pyc '或'。pyo ' 文件比从' .py '读取时的文件 文件;这是唯一更快的方法 关于”。Pyc ' or '。Pyo '文件是

运行.pyc文件的优点是Python不需要在运行它之前进行编译。由于Python会在运行.py文件之前编译为字节码,因此除此之外不应该有任何性能改进。

使用编译过的.pyc文件可以得到多大的改进?这取决于脚本的功能。对于只打印“Hello World”的非常简短的脚本,编译可能占启动和运行总时间的很大比例。但是对于长时间运行的脚本,相对于总运行时间,编译脚本的成本会减少。

您在命令行中命名的脚本永远不会保存到.pyc文件中。只有由“main”脚本加载的模块才会以这种方式保存。

初学者认为Python是通过.pyc文件编译的。.pyc文件是编译后的字节码,然后对其进行解释。因此,如果您之前运行过Python代码,并且手边有.pyc文件,那么第二次运行时它会运行得更快,因为它不必重新编译字节码

< >强编译器: 编译器是将高级语言翻译成机器语言的一段代码

<强>翻译: 解释器还将高级语言转换为机器可读的对等二进制。每次解释器获得要执行的高级语言代码时,它在将代码转换为机器代码之前将其转换为中间代码。代码的每一部分都被解释,然后按顺序分别执行,如果在代码的某一部分中发现错误,它将停止对代码的解释,而不翻译下一组代码。< / p >

< >强来源: http://www.toptal.com/python/why-are-there-so-many-pythons http://www.engineersgarage.com/contribution/difference-between-compiler-and-interpreter < / p >

优点:

第一:温和的、可克服的困惑。

第二:如果编译生成的文件明显更小,那么加载时间就会更快。对网络来说很不错。

第三:Python可以跳过编译步骤。在初始负载时更快。这对CPU和网络来说都是好事。

第四:注释越多,与源.py文件相比,.pyc.pyo文件就越小。

第五:只有.pyc.pyo文件的最终用户不太可能向您提供由他们忘记告诉您的未恢复更改引起的错误。

第六:如果你的目标是嵌入式系统,获得更小的尺寸 要嵌入的文件可能代表着一个显著的优点,而且架构是稳定的,所以缺点之一(下面详细说明)没有发挥作用

顶层编译

知道你可以用这种方式将顶级python源文件编译为.pyc文件是很有用的:

python -m py_compile myscript.py

这将删除注释。它保留docstrings完整。如果你也想摆脱docstrings(你可能想认真思考为什么要这样做),那么用这种方式编译…

python -OO -m py_compile myscript.py

...你会得到一个.pyo文件而不是.pyc文件;就代码的基本功能而言,它具有同样的可分发性,但由于剥离了docstrings的大小而更小(如果它一开始就有像样的docstrings,那么以后的工作就不太容易理解)。但请看下面的缺点三。

注意,python使用.py文件的日期(如果它存在)来决定是否应该执行.py文件,而不是.pyc.pyo文件——所以编辑你的.py文件,.pyc.pyo将被废弃,你所获得的任何好处都将失去。你需要重新编译它,以便再次获得.pyc.pyo的好处,不管它们可能是什么。

缺点:

首先:有一个“神奇的饼干”;在.pyc.pyo文件中,指明python文件在其中编译的系统架构。如果您将其中一个文件分发到不同类型的环境中,它就会崩溃。如果你分发的.pyc.pyo没有关联的.py来重新编译或touch,所以它取代了.pyc.pyo,最终用户也无法修复它。

第二:如果使用如上所述的-OO命令行选项跳过docstrings,那么没有人能够获得该信息,这可能会使代码的使用更加困难(或不可能)。

第三:Python的-OO选项也根据-O命令行选项实现了一些优化;这可能会导致操作上的变化。已知的优化有:

  • __abc0 = 1
  • assert语句被跳过
  • __debug__ = False

第四:如果你故意让你的python脚本在第一行中使用#!/usr/bin/python顺序的内容来可执行,这将在.pyc.pyo文件中被剥离,并且该功能将丢失。

第五:使用选项-O和-OO, assert语句不会被编译,从而消除了运行时验证的来源。你可以通过使用try except来弥补这一点,但这需要放弃assert语句,以便在将要编译的任何东西中使用。

第六:有些明显,但如果你编译你的代码,不仅它的使用会受到影响,而且其他人从你的工作中学习的潜力也会减少,通常是严重的。

我们使用编译后的代码分发给无法访问源代码的用户。基本上是为了防止没有经验的程序员在没有告诉我们的情况下意外地更改某些内容或修复错误。

这里没有涉及source-to-source-compiling。例如,nuitka将Python代码转换为C/ c++,并将其编译为直接在CPU上运行的二进制代码,而不是在较慢的虚拟机上运行的Python字节码。

这可以显著提高速度,或者当您的环境依赖于C/ c++代码时,它可以让您使用Python。