103

如何在 Python 中禁用断言?

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

我怎么做?

4

6 回答 6

99

如何在 Python 中禁用断言?

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

我演示每一个。

对于整个过程

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

例如:

$ python -Oc "assert False"

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

请注意,禁用我的意思是它也不执行它后面的表达式:

$ 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 中,设置然后清除环境变量:

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 )

代码中的单点

你继续你的问题:

如果断言失败,我不希望它抛出 AssertionError,而是继续。

如果您想要执行失败的代码,您可以捕获确保控制流未到达断言,例如:

if False:
    assert False, "we know this fails, but we don't get here"

或者您可以捕获断言错误:

try:
    assert False, "this code runs, fails, and the exception is caught"
except AssertionError as e:
    print(repr(e))

打印:

AssertionError('this code runs, fails, and the exception is caught')

并且您将从处理AssertionError.

参考

文档assert

像这样的断言语句:

assert expression #, optional_message

相当于

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

和,

内置变量__debug__True在正常情况下,False请求优化时(命令行选项-O)。

并进一步

分配给__debug__是非法的。内置变量的值在解释器启动时确定。

从使用文档:

-O

打开基本优化。这会将已编译(字节码)文件的文件扩展名从 .pyc 更改为 .pyo。另请参阅 PYTHONOPTIMIZE。

蟒蛇优化

如果将其设置为非空字符串,则等效于指定-O选项。如果设置为整数,则相当于指定-O多次。

于 2017-04-27T21:50:45.240 回答
61

使用 -O 标志调用 Python:

测试.py:

assert False
print('Done')

输出:

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
于 2009-08-13T16:53:41.960 回答
16

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

Python 文档中,它们之间的区别如下:

  • -O打开基本优化。这会将已编译(字节码)文件的文件扩展名从 .pyc 更改为 .pyo。

  • -OO除了-O优化之外,还要丢弃文档字符串。

要检查断言是启用还是禁用,请查看 的值__debug__

于 2014-01-24T05:45:49.307 回答
8

使用python -O

$ python -O
>>> assert False
>>> 
于 2009-08-13T16:52:12.180 回答
2

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

python -OO module.py
于 2009-08-13T16:52:09.653 回答
2

你不应该禁用断言。当注意力转移到别处时,他们会发现意料之外的错误。请参阅“十的幂”DOI维基百科)中的规则 5 。

raise语句,而不是assert语句:

if x_is_broken():
    raise RuntimeError('`x` is broken.')

raise无论运行 Python 的优化选项如何,这些语句仍然存在。此外,使用raise语句可以指定一种不同于AssertionError. 这对用户非常有用。而且,仅仅写一个raise声明就会提示问自己AssertionError那里是否是正确的选择。

此外,在编写raise语句时,我们被引导编写一条信息性消息,例如raise AssertionError('An error occurred with `x`.')。可以在语句写入错误消息assert(例如,assert x, 'An error occurred with `x`.'括号可用于写入多行的消息),但是可能会被遗忘。相反,raise AssertionError(....)要求....填写(表格raise AssertionError不常见,不推荐)。

在编写错误消息时,会显露出多少进一步的编码错误。

旁注:计算昂贵的断言检查只能在请求时运行。一种方法是:

import logging


log = logging.getLogger(__name__)


if log.getEffectiveLevel() < logging.DEBUG:
    if not check_expensive_property(x):
        raise RuntimeError('`x` is broken.')
于 2015-04-20T07:41:51.647 回答