Python的基本优化模式有什么用?(python -O)

54 投票
7 回答
14895 浏览
提问于 2025-04-15 15:46

Python 有一个选项 -O,可以用来启动解释器。这个选项会生成“优化过”的字节码(保存在 .pyo 文件中),如果你输入两次这个选项,它会去掉文档字符串。根据 Python 的手册页面:

-O 开启基本优化。这会把编译后的(字节码)文件的扩展名从 .pyc 改为 .pyo。如果输入两次,会去掉文档字符串。

我认为这个选项有两个主要功能:

  • 去掉所有的断言语句。这是为了提高速度,牺牲了一些程序状态的安全性。但是,难道不需要很多断言语句才能让这个优化有意义吗?你有没有什么代码是值得这样做的(而且是合理的)?

  • 去掉所有的文档字符串。在什么情况下,内存使用这么重要,以至于这样做是有好处的?为什么不把所有东西都写成 C 语言的模块呢?

这个选项有什么用呢?它在现实中真的有价值吗?

7 个回答

9

如果你的代码中有一些经常被调用的检查(比如在一个循环里),去掉这些检查确实能带来一些好处。举个极端的例子:

$ 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]

在实际情况中,节省的空间通常会少得多。

去掉文档字符串可能会减少你代码的大小,从而减小你需要处理的数据量。

在很多情况下,性能的影响可能微乎其微,但就像优化一样,唯一能确定的方法就是进行测量。

51

另一个使用 -O 标志的地方是,它会把内置变量 __debug__ 的值设置为 False

简单来说,你的代码可以有很多“调试”路径,比如:

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

在使用 -O 运行时,这些路径甚至不会被包含在 .pyo 文件的字节码中;这就像是一个简单的 C 语言中的 #ifdef 功能。

记住,只有在使用 -OO 标志时,文档字符串才会被去掉。

33

关于去掉断言语句:在C语言的世界里,这是一个常见的做法,很多人认为断言(ASSERT)的定义之一就是它在生产环境中不会被执行。去掉这些断言是否有影响,主要取决于断言的数量和它们所做的工作量,而不是单纯的数量:

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

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

至于去掉文档字符串,这似乎是从一个简单时代遗留下来的做法,虽然我想在一些内存有限的环境中,这可能会有一些影响。

撰写回答