Raise Try和Assert之间的区别

Def*_*eit 25 python assert raise

我已经学习了Python一段时间和raise功能,assert并且(我意识到他们两个都崩溃了应用程序,不像尝试 - 除外)非常相似,我看不到你会使用raiseassert结束的情况try.

那么,Raise,Try和Assert有什么区别?

Mic*_*zyz 30

assert cond, "text"
Run Code Online (Sandbox Code Playgroud)

扩展到类似的东西

if cond == False:
  raise AssertionError("text")
Run Code Online (Sandbox Code Playgroud)

使用assert是因为它更具可读性.

  • 请注意,优化编译时会删除“assert”语句,而“raise AssertionError()”则不会。 (16认同)

Moo*_*awr 30

断言:

当您想要根据特定条件"停止"脚本并返回一些内容以帮助更快地调试时使用:

list_ = ["a","b","x"]
assert "x" in list_, "x is not in the list"
print("passed") 
#>> prints passed

list_ = ["a","b","c"]
assert "x" in list_, "x is not in the list"
print("passed")
#>> 
Traceback (most recent call last):
  File "python", line 2, in <module>
AssertionError: x is not in the list
Run Code Online (Sandbox Code Playgroud)

提高:

有两个原因可用于此:

1 /与try和except块一起使用.提出您选择的错误,可以像下面那样自定义,如果您passcontiune脚本,则不会停止脚本; 或者可以是预定义的错误raise ValueError()

class Custom_error(BaseException):
    pass

try:
    print("hello")
    raise Custom_error
    print("world")
except Custom_error:
    print("found it not stopping now")

print("im outside")

>> hello
>> found it not stopping now
>> im outside
Run Code Online (Sandbox Code Playgroud)

注意到它没有停止?我们可以使用except块中的exit(1)来停止它.

2/Raise也可用于重新加载当前错误以将其传递到堆栈以查看是否有其他东西可以处理它.

except SomeError, e:
     if not can_handle(e):
          raise
     someone_take_care_of_it(e)
Run Code Online (Sandbox Code Playgroud)

Try/Except块:

完全按照你的想法,尝试一些东西,如果出现错误,你会抓住它并按照你喜欢的方式处理它.没有例子,因为上面有一个.

  • 请注意,就像 Ian Goldby 提到的那样,断言在优化时被删除。“assert”语句旨在作为实现的内部一致性检查。对于在代码的预期使用过程中可能发生的错误,请改为“引发”错误。 (2认同)

Joh*_*don 18

raise - 提出例外.

assert- 如果给定条件是(或不是),引发异常.

try- 执行一些可能引发异常的代码,如果是,请抓住它.


Rui*_*lho 18

断言

  • 应该只用于调试目的
  • 尽管与 Raise/Exceptions 类似,但它们有不同的用途,因为它们可用于指出无法从中恢复程序错误的场景
  • 断言总是引发 AssertionError 异常,它们的工作原理如下:

语法assert_stmt ::= "assert" expression1 ["," expression2]

在执行时它转换为

if __debug__:
  if not expression1:
    raise AssertionError(expression2)
Run Code Online (Sandbox Code Playgroud)
  • __debug__ 是一个内置标志,通常为真,但如果优化被触发,它将为假,因此断言将是死代码 => 在启动 Python 时使用 -O 和 -OO 标志禁用(或 CPython 中的 PYTHONOPTIMIZE 环境变量),所以,不要依赖它们来进行代码逻辑。
  • 由于前一点,不要使用断言进行数据验证
  • 断言的一个很好的用例 => 使程序“爆炸”,如果程序的某些意外状态应该使其在所有情况下都停止 => 因此,在捕获异常将使程序完全退出的情况下。
  • 如果你有一个没有错误的程序,那么断言将/不应该被触发,它们作为程序的健康检查
  • 在使用数据结构(例如元组)作为对于非空值总是评估为 True 的断言中的 expression1 时要小心=> 断言将始终被触发,破坏程序 - 例如:assert (<some_test>, 'warn string')=> 注意元组构造(错误! )

检查:Dan Bader 在 CI 上捕获虚假的 Python 断言

引发/异常

  • 它们的目的是处理程序逻辑处于异常状态但您知道从该状态恢复什么逻辑的情况
  • 当您引发异常时,您可以使异常的类型适合错误(更好地控制语义值)并稍后捕获它 => 这样您就可以创建多个您知道如何从中恢复并处理它们的异常类型
  • 它们是一种用于处理已知/预期的运行时错误场景的机制
  • 在使用 if 语句并在每个场景中引发验证异常时对数据验证很有用

尝试

  • 只是编码异常处理的语法元素

顺便说一句,我强烈推荐Dan Bader(来自realpython.com)的书“Python Tricks: The Book”


tde*_*ney 10

try/except阻止您捕获和管理异常.例外可以由raiseassert,以及大量错误触发,例如尝试索引空列表.raise通常在检测到错误情况时使用.assert类似但只有在满足条件时才会引发异常.

raiseassert有一个不同的哲学.您检测到的代码中存在许多"正常"错误并引发错误.也许网站不存在或参数值超出范围.

断言通常保留为"我发誓这不可能发生"的问题似乎无论如何都会发生.它更像是运行时调试而不是正常运行时错误检测.如果您使用-O标志或从.pyo文件而不是.pyc文件运行,则可以禁用断言,因此它们不应成为常规错误检测的一部分.

如果生产质量代码引发异常,那么弄清楚你做错了什么.如果它提出了AssertionError,你就会遇到更大的问题.


ruo*_*ola 6

当它们就位时,assert和之间没有区别raise AssertionError,它们将编译为完全相同的字节码:

import dis

def foo1(param):
    assert param, "fail"

def foo2(param):
    if not param:
        raise AssertionError("fail")

dis.dis(foo1)
print("*" * 60)
dis.dis(foo2)
Run Code Online (Sandbox Code Playgroud)

输出:

 4           0 LOAD_FAST                0 (param)
             2 POP_JUMP_IF_TRUE        12
             4 LOAD_GLOBAL              0 (AssertionError)
             6 LOAD_CONST               1 ('fail')
             8 CALL_FUNCTION            1
            10 RAISE_VARARGS            1
       >>   12 LOAD_CONST               0 (None)
            14 RETURN_VALUE
************************************************************
 7           0 LOAD_FAST                0 (param)
             2 POP_JUMP_IF_TRUE        12

 8           4 LOAD_GLOBAL              0 (AssertionError)
             6 LOAD_CONST               1 ('fail')
             8 CALL_FUNCTION            1
            10 RAISE_VARARGS            1
       >>   12 LOAD_CONST               0 (None)
            14 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)

但是请记住,assert使用-Oor-OO标志运行 Python 时,stataments 将被禁用,任何 raise 语句都不是这种情况。

  • 我相信使用 -O 优化器标志时情况并非如此。在这种情况下,“raise AssertionError”仍然有效,但“assert”被忽略 (2认同)