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

u0b*_*6ae 47 python optimization assert bytecode

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

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

我认为这个选项的两个主要特点是:

  • 删除所有断言语句.为了速度,这可以防止腐败的程序状态.但是,你不需要大量的断言声明才能有所作为吗?你有任何值得的代码(并且理智吗?)

  • 剥离所有文档字符串.什么应用程序的内存使用如此关键,这是一个胜利?为什么不将所有内容都推入用C编写的模块?

这个选项有什么用?它有真实世界的价值吗?

tzo*_*zot 44

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

所以,基本上,你的代码可以有很多"调试"路径,如:

if __debug__:
     # output all your favourite debugging information
     # and then more
Run Code Online (Sandbox Code Playgroud)

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

请记住,只有在标志出现时才会删除文档字符串-OO.

  • 哇.我以为你想知道这个选项的真实用途是什么.谢谢你找到我的答案旁边没用.顺便说一句,如果你想让某人为Guido和其他Python核心团队的选择辩护,你不应该在这里提问; 最后,你*可以*依赖于使用的特定模式,程序员可以控制是否使用优化; 在SO中问一个相关的问题.我在此宣布你的假设接下来是错误的,我的时间接下来就丢失了.干杯.很抱歉让你失望. (23认同)
  • 对于我的问题得到很多答案,我没有理由感到失望 - 我喜欢stackoverflow中的对话.我的意思是我说的但我谈的是你展示的例子.您展示它或您自己的事实根本不会被判断为负面. (3认同)
  • 顺便提一下,各种现实世界的开源框架已经利用`__debug__` - 包括distlib,html5lib,IPython,Jinja2,matplotlib,python-ldap,speechd以及太多官方CPython stdlib模块来计算(例如,`imaplib` ,`pickletools`,`statistics`,`unittest`).`__debug__` _absolutely_有它的位置.老实说,我希望看到它更多地利用它. (3认同)

Ned*_*der 30

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

def foo(x):
    assert x in huge_global_computation_to_check_all_possible_x_values()
    # ok, go ahead and use x...
Run Code Online (Sandbox Code Playgroud)

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

至于剥离文档字符串,它似乎从一个简单的时间看起来像一个古怪的保留,虽然我想有内存约束的环境,它可以有所作为.

  • 内存速度增长远远慢于CPU速度,*尤其是*如果您认为我们继续添加处理器比添加内存带宽更快.因此,内存是新磁盘,L2缓存是新内存.L2缓存*很小*(与内存相比),它们实际上越来越小.(例如,Core2有6144KiB,i7只有256KiB.)因此,计算字节实际上再次变得有用. (19认同)
  • 除非指定-O,否则像PyOpenGL和pyglet这样的OpenGL库在运行时会执行一些非常昂贵的安全检查断言. (2认同)

oef*_*efe 7

如果你在频繁调用的代码中有断言(例如在内部循环中),剥离它们肯定会产生影响.极端的例子:

$ 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]
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • 另外,`assert`是一个声明,我打算用"`assert True`",而不是'assert(True)`.当你添加消息时,这变得很重要,因为`assert a == b,'必须为true"`与`assert(a == b,"Must be true")`非常不同,特别是后者总是通过. (2认同)

Mik*_*ham 7

我从来没有遇到过使用的充分理由-O.我一直认为它的主要目的是在未来的某些时候增加一些有意义的优化.

  • 嗯,它确实做了几件事,它们通常都不是那么有用. (3认同)

z0r*_*z0r 7

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

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

assert not any(a == b for a, b in zip(path, path[1:]))
Run Code Online (Sandbox Code Playgroud)

我喜欢这个简单的声明在开发过程中带来的安心和清晰。在生产中,代码处理一些大图,这一行可能会占用高达 66% 的运行时间。因此,运行 with-O会显着加快速度。


Nic*_*ood 5

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

我个人从来没有-O直接使用过.

  • 创建独立可执行文件时,不需要文档字符串.它们只占用内存空间. (4认同)