在Python中检查__debug__和其他一些条件

时间:2013-07-10 19:55:57

标签: python debugging compilation

在Python中,有时我想做(1)

之类的事情
if __debug__ and verbose: print "whatever"

如果Python使用-O运行,那么我希望整条代码消失,就像我刚才那样(2)

if __debug__: print "whatever"

甚至(3)

if __debug__:
    if verbose: print foo

然而,这似乎并未发生(见下文)。有没有办法可以通过紧凑的代码获得#3的运行时效率,更像是#1?

以下是我测试的方法,我没有得到我想要的高效代码:

#!/usr/bin/python2.7

from dis import dis
import sys

cmds = ["""
def func ():
    if __debug__ and 1+1: sys.stdout.write('spam')""",   """
def func():
    if __debug__: sys.stdout.write('ham')""",     """
def func():
    __debug__ and sys.stdout.write('eggs')"""]

print "__debug__ is", __debug__, "\n\n\n"

for cmd in cmds:
    print "*"*80, "\nSource of {}\n\ncompiles to:".format(cmd)
    exec(cmd)
    dis(func)
    print "\n"*4

运行此功能

__debug__ is False 



******************************************************************************** 
Source of 
def func ():
    if __debug__ and 1+1: sys.stdout.write('spam')

compiles to:
  3           0 LOAD_GLOBAL              0 (__debug__)
              3 POP_JUMP_IF_FALSE       31
              6 LOAD_CONST               3 (2)
              9 POP_JUMP_IF_FALSE       31
             12 LOAD_GLOBAL              1 (sys)
             15 LOAD_ATTR                2 (stdout)
             18 LOAD_ATTR                3 (write)
             21 LOAD_CONST               2 ('spam')
             24 CALL_FUNCTION            1
             27 POP_TOP             
             28 JUMP_FORWARD             0 (to 31)
        >>   31 LOAD_CONST               0 (None)
             34 RETURN_VALUE        





******************************************************************************** 
Source of 
def func():
    if __debug__: sys.stdout.write('ham')

compiles to:
  3           0 LOAD_CONST               0 (None)
              3 RETURN_VALUE        





******************************************************************************** 
Source of 
def func():
    __debug__ and sys.stdout.write('eggs')

compiles to:
  3           0 LOAD_GLOBAL              0 (__debug__)
              3 JUMP_IF_FALSE_OR_POP    21
              6 LOAD_GLOBAL              1 (sys)
              9 LOAD_ATTR                2 (stdout)
             12 LOAD_ATTR                3 (write)
             15 LOAD_CONST               1 ('eggs')
             18 CALL_FUNCTION            1
        >>   21 POP_TOP             
             22 LOAD_CONST               0 (None)
             25 RETURN_VALUE        

1 个答案:

答案 0 :(得分:4)

不,你不能。 Python的编译器不够智能,无法检测它在什么情况下可以删除代码块和if语句。

否则Python必须进行大量的逻辑推理。比较:

if __debug__ or verbose:

if __debug__ and verbose:
例如,

。 Python必须在编译时检测这两个表达式之间的差异;一个可以优化,另一个不能。

请注意,使用和不使用if __debug__语句的代码之间的运行时间差异非常小,其他条件相同。实际上,一个小的恒定值测试和跳跃并不是什么大惊小怪的事。