50

Python 有一个-O可以用来执行解释器的标志。该选项将生成“优化”字节码(写入 .pyo 文件),并给出两次,它将丢弃文档字符串。从 Python 的手册页:

-O 打开基本优化。这会将已编译(字节码)文件的文件扩展名从 .pyc 更改为 .pyo。给出两次,导致文档字符串被丢弃。

在我看来,此选项的两个主要功能是:

  • 剥离所有断言语句。这牺牲了对腐败程序状态的防御以换取速度。但是你不需要大量的断言语句来产生影响吗?您是否有任何值得这样做的代码(并且理智?)

  • 剥离所有文档字符串。在哪个应用程序中内存使用如此关键,以至于这是一个胜利?为什么不将所有内容都放入用 C 编写的模块中呢?

这个选项有什么用?它有现实价值吗?

4

7 回答 7

49

-O该标志的另一个用途是__debug__内置变量的值设置为False.

因此,基本上,您的代码可以有很多“调试”路径,例如:

if __debug__:
     # output all your favourite debugging information
     # and then more

在 下运行时-O,它甚至不会作为字节码包含在.pyo文件中;一个穷人的 C-ish #ifdef。

请记住,当标志为-OO.

于 2009-11-08T22:35:40.063 回答
32

关于剥离断言语句:这是 C 世界中的标准选项,许多人认为 ASSERT 的部分定义是它不在生产代码中运行。剥离它们是否会产生影响,与其说有多少断言,不如说取决于这些断言做了多少工作:

def foo(x):
    assert x in huge_global_computation_to_check_all_possible_x_values()
    # ok, go ahead and use x...

当然,大多数断言不是那样的,但重要的是要记住你可以做那样的事情。

至于剥离文档字符串,它确实看起来像是从更简单的时代开始的一种古朴的保留,尽管我猜在内存受限的环境中它可能会有所作为。

于 2009-11-07T14:07:25.173 回答
8

如果您在经常调用的代码中有断言(例如在内部循环中),那么剥离它们肯定会有所作为。极端例子:

$ python    -c 'import timeit;print timeit.repeat("assert True")'
[0.088717937469482422, 0.088625192642211914, 0.088654994964599609]
$ python -O -c 'import timeit;print timeit.repeat("assert True")'
[0.029736995697021484, 0.029587030410766602, 0.029623985290527344]

在实际情况下,节省的费用通常会少得多。

剥离文档字符串可能会减少代码的大小,从而减少工作集。

在许多情况下,性能影响可以忽略不计,但与优化一样,唯一确定的方法是测量。

于 2009-11-07T14:11:28.583 回答
7

我从来没有遇到过使用-O. 我一直认为它的主要目的是在将来的某个时候添加一些有意义的优化。

于 2009-11-07T18:18:41.017 回答
6

但是你不需要大量的断言语句来产生影响吗?您是否有任何值得这样做的代码(并且理智?)

例如,我有一段代码可以获取图中节点之间的路径。我在函数末尾有一个断言语句来检查路径是否不包含重复项:

assert not any(a == b for a, b in zip(path, path[1:]))

我喜欢这个简单的陈述在开发过程中给人的安心和清晰。在生产环境中,代码会处理一些大图,而这一行可能会占用高达 66% 的运行时间。因此,运行 with-O可以显着提高速度。

于 2017-05-19T03:43:21.863 回答
5

我想最重的用户-Opy2exe py2app和类似的。

我个人从来没有-O直接找到用途。

于 2009-11-07T14:08:28.027 回答
4

你几乎已经明白了:它几乎什么都不做。除非您对 RAM 造成严重伤害,否则您几乎永远不会看到速度或内存增加。

于 2009-11-07T14:08:15.703 回答