关于调试:在Python中禁用断言

Disable assertions in Python

如何禁用Python中的断言?

也就是说,如果一个断言失败了,我不希望它抛出一个AssertionError,而是继续下去。

我该怎么做?


使用-o标志调用python:

测试:PY:

1
2
assert(False)
print 'Done'

输出:

1
2
3
4
5
6
7
8
C:\temp\py>C:\Python26\python.exe test.py
Traceback (most recent call last):
  File"test.py", line 1, in <module>
    assert(False)
AssertionError

C:\temp\py>C:\Python26\python.exe -O test.py
Done


How do I disable assertions in Python?

有多种方法会影响单个进程、环境或单个代码行。

我演示每一个。

整个过程

使用-O标志(大写O)禁用进程中的所有assert语句。

例如:

1
2
3
4
5
6
$ python -Oc"assert False"

$ python -c"assert False"
Traceback (most recent call last):
  File"<string>", line 1, in <module>
AssertionError

注意,通过disable,我的意思是它也不执行它后面的表达式:

1
2
3
4
5
6
$ python -Oc"assert 1/0"

$ python -c"assert 1/0"
Traceback (most recent call last):
  File"<string>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero

对于环境

也可以使用环境变量设置此标志。

这将影响使用或继承环境的每个进程。

例如,在Windows中,设置然后清除环境变量:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
C:\>python -c"assert False"
Traceback (most recent call last):
  File"<string>", line 1, in <module>
AssertionError
C:\>SET PYTHONOPTIMIZE=TRUE

C:\>python -c"assert False"

C:\>SET PYTHONOPTIMIZE=

C:\>python -c"assert False"
Traceback (most recent call last):
  File"<string>", line 1, in <module>
AssertionError

在Unix中相同(为各自的功能使用set和unset)

代码中的单点

继续提问:

if an assertion fails, I don't want it to throw an AssertionError, but to keep going.

如果您希望执行失败的代码,可以捕获断言错误:

1
2
3
4
try:
    assert False,"we know this fails"
except AssertionError as e:
    print(repr(e))

哪些印刷品:

1
AssertionError('we know this fails',)

你将继续从你处理AssertionError的那一点出发。

工具书类

assert文件中:

像这样的断言语句:

1
assert expression #, optional_message

等于

1
2
if __debug__:
    if not expression: raise AssertionError #(optional_message)

而且,

the built-in variable __debug__ is True under normal circumstances, False when optimization is requested (command line option -O).

从使用文档:

-O

Turn on basic optimizations. This changes the filename extension for compiled (bytecode) files from .pyc to .pyo. See also PYTHONOPTIMIZE.

PYTHONOPTIMIZE

If this is set to a non-empty string it is equivalent
to specifying the -O option. If set to an integer, it is equivalent to
specifying -O multiple times.


已经给出的两个答案都是有效的(使用命令行上的-O-OO调用python)。

它们之间的区别如下:

  • -O启用基本优化。这将更改文件扩展名用于从.pyc到.pyo的已编译(字节码)文件。

  • 除了-O优化之外,-OO放弃docstring。

(来自python文档)


使用python -O

1
2
3
$ python -O
>>> assert False
>>>

您不应该禁用(大多数)断言。当注意力集中在其他地方时,他们会捕捉到意料之外的错误。见"十的力量"中的规则5。

相反,通过以下方式来保护一些昂贵的断言检查:

1
2
3
4
5
6
import logging
logger = logging.getLogger(__name__)

if logger.getEffectiveLevel() < logging.DEBUG:
    ok = check_expensive_property()
    assert ok, 'Run !'

保留重要断言并允许优化assert语句的一种方法是在选择语句中提高它们:

1
2
if foo_is_broken():
    raise AssertionError('Foo is broken!')


在优化模式下运行应该做到:

1
python -OO module.py