Python 什么';提升、尝试和断言之间的区别是什么?

Python 什么';提升、尝试和断言之间的区别是什么?,python,assert,raise,Python,Assert,Raise,我学习Python已经有一段时间了,raise函数和assert非常相似(我意识到这两个函数都会使应用程序崩溃,与try-except不同),我看不出有哪种情况下你会使用raise或assert而不是try 那么,raise、try和assert之间有什么区别呢?可以在运行时用于检查条件,但是如果从Python请求优化,则会删除。扩展形式为: 断言条件、消息 相当于: 如果调试: 如果不是条件: 引发断言错误(消息) 其中isTrue是Python没有使用选项-O启动 因此,语句assert

我学习Python已经有一段时间了,
raise
函数和
assert
非常相似(我意识到这两个函数都会使应用程序崩溃,与try-except不同),我看不出有哪种情况下你会使用
raise
assert
而不是
try

那么,
raise
try
assert
之间有什么区别呢?

可以在运行时用于检查条件,但是如果从Python请求优化,则会删除。扩展形式为:

断言条件、消息
相当于:

如果调试:
如果不是条件:
引发断言错误(消息)
其中is
True
是Python没有使用选项
-O
启动

因此,语句
assert condition,message
类似于:

如果不是条件:
引发断言错误(消息)
在这种情况下,两者都会引发一个
AssertionError
。不同之处在于,
assert condition,message
可以通过优化从执行的字节码中删除(当这些被启用时——默认情况下它们不应用于CPython)。相反,
raiseassertionError(message)
在所有情况下都将被执行


因此,如果代码在任何情况下都应该检查并在检查失败时引发一个
AssertionError
,则有必要写入
如果没有条件:引发AssertionError

引发一个异常

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


try
-执行一些可能引发异常的代码,如果是,则捕获它。

异常是Python(和其他一些语言)用来处理执行代码时出现的错误的
raiseexceptionname
表示代码中存在错误,并通过引发与该问题相关联的异常来指定问题的类型<代码>断言表达式
计算
表达式
,如果为false,则引发异常

try
用于执行可能引发预期异常的代码。您可以“捕获”异常并在代码中处理它,而不是停止程序

例如:假设您有一本词典和一个列表。您希望从字典中的列表中查找内容,直到找到字典中没有的内容:

try:
    for item in my_list:
        print(my_dictionary[item])
except KeyError as e: #KeyError is the Exception raised when a key is not in a dictionary
    print('There is no {} in the dictionary'.format(e.args[0]))

try/except
块用于捕获和管理异常。异常可能由
raise
assert
,以及大量错误(如尝试为空列表编制索引)触发<代码>升高通常在检测到错误情况时使用<代码>断言类似,但只有满足条件时才会引发异常

raise
assert
有不同的理念。代码中有许多“正常”错误,您可以在这些错误上检测并引发错误。可能网站不存在或参数值超出范围

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

若生产质量代码引发异常,那个么找出你们做错了什么。如果它引发了一个断言错误,那么您就遇到了一个更大的问题。

断言:

当您希望基于某个条件“停止”脚本并返回有助于更快调试的内容时使用:

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
注意到它没有停止吗?我们可以使用except块中的exit(1)停止它

2/Raise还可用于重新引发当前错误,将其向上传递到堆栈,以查看是否有其他内容可以处理它

except SomeError, e:
     if not can_handle(e):
          raise
     someone_take_care_of_it(e)

尝试/排除块:


完全按照你的想法去做,尝试一些事情,如果出现错误,你会抓住它,然后以你喜欢的方式处理它。没有示例,因为上面有一个。

测试代码通常使用Assert来确保某些功能正常工作:

def test_bool():
    assert True != False
Where as try、raise和except-up异常处理,这是python中处理和传播错误的首选方法

如果出现问题,大多数库和python内置程序都会引发一种或另一种类型的异常。通常,在您自己的代码中,当您检测到出错时,您也会希望引发异常。例如,您正在编写一个电子邮件地址验证程序,如果该地址不包含@符号,您希望引发一个异常。你可以有这样的东西(这是玩具代码,不要像这样验证电子邮件):

然后在代码中的其他地方,您可以调用validate_email函数,如果它失败,将引发异常

try:
    validate_email("Mynameisjoe.com")
except ValueError as ex:
    print("We can do some special invalid input handling here, Like ask the user to retry the input")
finally:
    close_my_connection()
    print("Finally always runs whether we succeed or not. Good for clean up like shutting things down.")
需要知道的重要一点是,当引发异常时,它会向上传递调用堆栈,直到找到处理程序为止。如果它从未找到处理程序,那么它将导致程序崩溃,并出现异常和堆栈跟踪

你不想做的一件事是:

if __name__ == '__main__':
    try:
        print(1/0)
    except Exception as ex:
        pass
import logging
if __name__ == '__main__':
    try:
        print(1/0)
    except Exception as ex:
        logging.exception(ex)
        raise
现在你无法知道你的应用程序为什么会爆炸

有一件事你会经常看到,那就是:

if __name__ == '__main__':
    try:
        print(1/0)
    except Exception as ex:
        pass
import logging
if __name__ == '__main__':
    try:
        print(1/0)
    except Exception as ex:
        logging.exception(ex)
        raise

在这种情况下,由于没有参数,因此raise将重新引发相同的错误。通常,在web代码中,您会看到类似的情况,不会重新引发异常,因为它会将500错误发送到客户端,然后继续执行下一个请求,因此在这种情况下,您不希望程序结束。

断言

  • 应仅用于调试目的
  • 尽管与引发/异常类似,但它们有不同的用途,因为它们对点场景很有用
    if __debug__:
      if not expression1:
        raise AssertionError(expression2)
    
    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)
    
     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
    
    def raiseif(cond, msg="", exc=AssertionError):
        if cond:
            raise exc(msg)
    
    raiseif(x != y, "x should equal y")