277

为什么要编译 Python 脚本?您可以直接从 .py 文件运行它们,它工作正常,那么有性能优势还是什么?

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

4

10 回答 10

307

它被编译成字节码,可以更快地使用。

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

Ben Blank的重要补充:

值得注意的是,虽然运行已编译的脚本具有更快的启动 时间(因为它不需要编译),但它并没有运行得更快。

于 2009-01-22T23:06:13.687 回答
87

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

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

从 '.pyc' 或 '.pyo' 文件读取程序不会比从 '.py' 文件读取程序运行得更快;'.pyc' 或 '.pyo' 文件唯一更快的是它们的加载速度。

运行 .pyc 文件的优点是 Python 不必在运行之前产生编译它的开销。由于 Python 无论如何都会在运行 .py 文件之前编译为字节码,因此除此之外不应该有任何性能改进。

使用已编译的 .pyc 文件可以获得多少改进?这取决于脚本的作用。对于仅打印“Hello World”的非常简短的脚本,编译可能占总启动和运行时间的很大一部分。但是对于运行时间较长的脚本,编译脚本相对于总运行时间的成本会降低。

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

于 2009-01-22T23:14:33.407 回答
61

优点:

第一:温和的、可战胜的混淆。

第二:如果编译后的文件明显更小,您将获得更快的加载时间。很适合网络。

第三:Python可以跳过编译步骤。在初始负载下更快。非常适合 CPU 和网络。

第四:你评论的越多,.pycor.pyo文件与源.py文件相比就越小。

第五:手头只有一个.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文件而不是.pycor.pyo文件 --- 因此编辑您的 .py 文件,并且.pycor.pyo已过时并且您获得的任何好处都将丢失。您需要重新编译它才能再次获得.pyc.pyo收益,就像它们可能一样。

缺点:

.pyc首先:和文件中有一个“魔术cookie” .pyo,指示编译python文件的系统架构。如果将这些文件中的一个分发到不同类型的环境中,它将破坏。如果您分发.pycor.pyo没有关联.py的重新编译,或者touch它取代.pycor .pyo,最终用户也无法修复它。

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

第三:Python的-OO选项也按照-O命令行选项实现了一些优化;这可能会导致操作发生变化。已知的优化是:

  • sys.flags.optimize= 1
  • assert语句被跳过
  • __debug__= 假

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

第五:有点明显,但是如果你编译你的代码,不仅会影响它的使用,而且其他人从你的工作中学习的可能性也会降低,而且通常会很严重。

于 2014-04-23T22:26:10.910 回答
12

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

这可能会导致显着的加速,或者它可以让您在您的环境依赖于 C/C++ 代码时使用 Python。

于 2017-12-23T19:30:11.707 回答
11

运行已编译的 python 会提高性能。但是,当您将 .py 文件作为导入模块运行时,python 将编译并存储它,只要 .py 文件不更改,它将始终使用编译后的版本。

使用文件时使用任何被解释的语言,该过程看起来像这样:
1. 文件由解释者处理。
2. 文件被编译
3. 编译后的代码被执行。

显然,通过使用预编译代码,您可以消除第 2 步,这适用于 python、PHP 等。

这是一篇有趣的博客文章,解释了不同之处http://julipedia.blogspot.com/2004/07/compiled-vs-interpreted-languages.html
这是一个解释 Python 编译过程的条目http://effbot.org/zone /python-compile.htm

于 2009-01-22T23:03:26.470 回答
9

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

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

您可以在Python 文档中阅读更多相关信息。

于 2009-01-22T23:09:53.650 回答
7

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

于 2009-01-22T23:02:39.467 回答
4

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

于 2015-06-15T16:14:32.880 回答
2

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

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

于 2009-01-22T23:03:58.043 回答
1

初学者假设 Python 是因为 .pyc 文件而编译的。.pyc 文件是编译后的字节码,然后会被解释。因此,如果您之前运行过 Python 代码并且手边有 .pyc 文件,那么第二次运行速度会更快,因为它不必重新编译字节码

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

口译员: 口译员还将高级语言转换为机器可读的二进制等价物。每当解释器获得要执行的高级语言代码时,它都会先将代码转换为中间代码,然后再将其转换为机器代码。代码的每一部分都被解释,然后按顺序单独执行,如果在代码的一部分中发现错误,它将停止代码的解释,而不翻译下一组代码。

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

于 2014-01-08T14:13:34.350 回答