python assert用-O触发 [英] python assert fires with -O

查看:151
本文介绍了python assert用-O触发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试确保在使用-O时不会由python执行断言.但是我的测试程序表明它总是被执行.我专门在命令行上使用-O,并且在构建和安装过程中同时运行setup.py时使用了-O.在我提交错误报告之前,我想确保我没有犯任何菜鸟错误...

I am trying to make sure that an assert is not executed by python when using -O. My test program however indicates that it is always executed. I specifically use -O on the command line and I used -O when I ran setup.py with both build and install. Before I submit a bug report I wanted to make sure I did not do any rookie mistakes...

那么我是否需要做其他事情或做别的事情,以使断言不被执行?

So do I need to do something else or different so that the assert is not executed?

我的简单脚本:

print __debug__

if __debug__:
    print "True branch"
else:
    print "False branch"

assert(False)

在独立运行时有效.打印:

works when run standalone. Prints:

False
False branch

当我在主程序中复制此代码段时(我不能在此处包括...),我得到:

When I copy this snippet in the main program (that I cannot include here...) I get:

False
True branch
AssertionError

我完全感到困惑.在Mac上为Python 2.7.6. (对于Mac,很抱歉,我必须在工作中使用它.)

I am utterly confused how that can come about. This Python 2.7.6 on a Mac. (Sorry about the Mac, I have to use it for work.)

推荐答案

您可以通过使用-O标志直接运行.pyc文件 来实现您描述的效果.那是对事物本来应该工作的方式的滥用.您要:

You can achieve the effect you describe by running a .pyc file directly with the -O flag. That's an abuse of the way things are supposed to work. You want to either:

  1. 运行带有或不带有-O标志的.py文件(通常的方法),或者
  2. 在没有-O标志的情况下运行.pyc文件
  3. 使用-O标志运行.pyo文件 .
  1. Run the .py file with or without the -O flag (the usual approach), or
  2. Run the .pyc file without the -O flag, or
  3. Run the .pyo file with the -O flag.

如果运行带有-O标志的.pyc文件,或者运行没有.pyo标志的.pyo文件,您将得到类似这样的惊喜.

If you run a .pyc file with the -O flag, or a .pyo file without it, you're going to get surprises like this one.

发生的事情是,在编译时,窥孔优化器已经优化掉了if __debug__分支,因此.pyc.pyo文件将无条件执行相应的分支.然后,当您使用错误的-O规范运行时,将以__debug__的值运行,该值与编译时应用的优化不匹配.

What's happening is that at compile time the peephole optimiser has optimised away the if __debug__ branches, so the .pyc or .pyo files will execute the appropriate branch unconditionally. Then when you run with the wrong -O specification, you'll be running with a value of __debug__ that doesn't match the optimisation that was applied at compile time.

前一段时间在Python问题跟踪器上报告了一个类似问题,尽管事实恰恰相反情况:有人在不使用-O标志的情况下运行.pyo文件.

There was a similar issue reported on the Python issue tracker a while back, though that was the opposite situation: someone running a .pyo file without using the -O flag.

一个简单的例子:假设我的当前目录中有一个类似于您的名为"debug_example.py"的文件:

A quick example: suppose I've got a file somewhat like yours named "debug_example.py" sitting in my current directory:

noether:Desktop mdickinson$ cat debug_example.py
def main():
    print "__debug__ is {}".format(__debug__)
    if __debug__:
        print "__debug__ is True"
    else:
        print "__debug__ is False"

if __name__ == '__main__':
    main()

如果我们直接执行文件(带有或不带有-O标志),我们将看到预期的结果:

If we execute the file directly, with or without the -O flag, we see the expected results:

noether:Desktop mdickinson$ python2 debug_example.py
__debug__ is True
__debug__ is True
noether:Desktop mdickinson$ python2 -O debug_example.py
__debug__ is False
__debug__ is False

现在,使用方便的 py_compile 模块. (在您的情况下,该编译可能是setup.py安装的一部分.):

Now let's compile this file to a "debug_example.pyc" file using the handy py_compile module. (In your case this compilation is likely being performed as part of the setup.py installation.):

noether:Desktop mdickinson$ python2 -m py_compile debug_example.py
noether:Desktop mdickinson$ ls -l debug_example.pyc
-rw-r--r--  1 mdickinson  staff  350 24 Mar 21:41 debug_example.pyc

现在我们执行debug_example.pyc文件,但是(错误地)使用-O标志,Python感到困惑:

Now we execute the debug_example.pyc file, but (wrongly) using the -O flag, and Python gets confused:

noether:Desktop mdickinson$ python2 -O debug_example.pyc
__debug__ is False
__debug__ is True

我们可以使用 Python的dis模块来查看模块:

We can use Python's dis module to see the bytecode inside the module:

Python 2.7.6 (default, Nov 18 2013, 15:12:51) 
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.2.79)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import debug_example
>>> import dis
>>> dis.dis(debug_example)
Disassembly of main:
  2           0 LOAD_CONST               1 ('__debug__ is {}')
              3 LOAD_ATTR                0 (format)
              6 LOAD_GLOBAL              1 (__debug__)
              9 CALL_FUNCTION            1
             12 PRINT_ITEM          
             13 PRINT_NEWLINE       

  4          14 LOAD_CONST               2 ('__debug__ is True')
             17 PRINT_ITEM          
             18 PRINT_NEWLINE       
             19 LOAD_CONST               0 (None)
             22 RETURN_VALUE        

请注意,根本没有与if语句相对应的字节码:我们看到了无条件打印的'__debug__ is True'.

Note that there's no bytecode corresponding to the if statement there at all: we see an unconditional printing of '__debug__ is True'.

解决方案:不要直接执行.pyc.pyo文件:执行.py文件,然后让Python弄清楚是适当使用.pyc还是.pyo.

Solution: don't execute the .pyc or the .pyo files directly: execute the .py file and let Python figure out whether to use the .pyc or .pyo as appropriate.

这篇关于python assert用-O触发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆