Python——异常处理机制

news2024/10/5 13:46:29

Python 异常处理机制

    • Python异常与异常处理机制
    • 针对 Traceback 的解读
    • try-except-else-finally
      • except语句
        • except语句的机制
        • 在 except 语句中引用当前被处理的 Python 异常
      • finally语句
        • finally语句执行后才能抛出未被处理的异常
        • finally中执行return会导致异常丢失
    • raise 语句
      • raise 语句以及异常对象
      • raise…from 语句
    • Python 异常的基类 BaseException

Python异常与异常处理机制

Python使用称为异常的特殊对象来管理程序执行期间发生的错误(Python中一切皆对象,包括异常也是对象)。每当发生程序错误,都会创建一个异常对象。如果编写了处理该异常的代码,程序将继续运行;但是如果未编写代码对异常进行处理,程序将停止并显示traceback,其中包含有关异常的报告

异常处理是编程语言或计算机硬件里的一种机制,用于处理软件或信息系统中出现的异常状况,即超出程序正常执行流程的某些特殊条件。异常处理机制是使用 try-except 代码块处理异常,try-except 代码块让Python执行指定的操作,同时告诉Python发生异常时怎么办。使用try-except 代码块时,即便出现异常,程序也将继续运行,同时显示你编写的友好的错误消息,而不是令用户迷惑的traceback

Python提供了两个非常重要的功能来处理程序在运行中出现的异常和错误。经常使用的是try…except语句,拓展一下就是try-except-else-finally,另一个是断言,即assert

针对 Traceback 的解读

Traceback 是 Python 错误信息的报告,当你的程序导致异常时,Python 将打印 Traceback 以帮助你知道哪里出错了。虽然 Python 的 Traceback 提示信息看着挺复杂,但是里面存在丰富的信息,可以帮助你诊断和修复代码中引发异常的原因,以及定位到具体哪个文件的哪行代码出现的错误,这样有助于我们编写对应的异常处理代码来捕获异常,并给出合适的错误提示信息。所以说学会看懂 Traceback 信息是非常重要的

下面给出一个案例进行分析,这是一种导致Python引发异常的简单错误:除0

# calculate.py文件的内容
def divide(a, b):	# 进行除法运算的函数
    return a / b

# main.py文件的内容
from calculate import divide

divide(5, 0)

# 抛出异常:
"""
Traceback (most recent call last):
  File "C:\编程\Python代码\test\main.py", line 3, in <module>
    divide(5, 0)
  File "C:\编程\Python代码\test\calculate.py", line 2, in divide
    return a / b
ZeroDivisionError: division by zero
"""
  • 错误输出的最后一行一般会告诉你引发了什么类型的异常,以及关于该异常的一些相关信息,所以看错误信息的最后一行就能获知到错误的原因
    • 在上述 traceback 中,最后一行指出的错误 ZeroDivisionError 就是一个异常对象,并且给出了具体的描述 division by zero,即表示因为除0,导致程序抛出该异常
  • 错误输出的前面几行的阅读顺序应该是由下而上的,因为越往上,离抛出异常的实际位置越远,越难定位到抛出异常的代码
  • 这一部分要每连续两行为一组进行阅读。其中每组的第1行会告诉你是在哪个文件的、哪个函数的、哪一行出错了,也就是会更直接的告诉你错误发生的位置;每组的第2行会把报错的那一行代码显示出来
  • 比如在程序里A函数调用了B函数,然后B函数调用了C函数,而C函数报错了,那么 traceback 中的前几行从下至上的顺序来看,会先显示C函数的信息,再显示B函数的信息,再显示A函数的信息,而且每一个函数的信息都是按两行来组织的,其中第1行展示位置,第2行展示代码
    • 在上述 traceback 中,前面几行中的最后一行定位的位置为位于 calculate.py 文件中的第2行,并且位于 divide 函数代码块中,具体抛出异常的代码为"return a / b"
    • 然后我们看上一行,定位的位置为位于 main.py 文件中的第3行,并且位于引入模块的代码中,具体抛出异常的代码为"divide(5, 0)"
  • 最上面第一行的内容是固定不变的,始终Traceback (most recent call last)”,可以忽略

try-except-else-finally

  • try:正常情况下,程序计划执行的语句
  • except:程序异常时执行的语句
  • else:程序无异常即try段代码正常执行后会执行该语句
    • 当try语句的相关代码中的return,continue或break语句被执行时,else语句将被忽略
  • finally:不管有没有异常,都会执行的语句
    • 具体来说,当try,except或else语句的相关代码中存在某些跳转语句时,比如break,continue和return,与finally语句相关的代码将在这些跳转语句执行之前被执行
    • 在处理 Python 异常的过程中,一些代码需要始终被执行,无论是否有 Python 异常被抛出,或 Python 异常是否被处理。使用finally语句可以达成上述目标,该语句之后的代码通常与清理工作有关,比如,关闭打开的文件

运行逻辑1:首先运行try中的代码块,当出现异常时,终止try中代码块的执行,立即执行except中的代码块,最后执行finally中的代码块

try:
    print('输出:我是try1')
    a = 5 / 0
    print('输出:我是try2')

except :
    print('输出:我是except')

else :
    print('输出:我是else')

finally :
    print('输出:我是finally')

# 输出结果:
"""
输出:我是try1
输出:我是except
输出:我是finally
"""

运行逻辑2:首先运行try中的代码块,当执行完毕后,代码始终没有抛出异常,继续执行else中的代码块,最后执行finally中的代码块

try:
    print('输出:我是try1')
    a = 5 / 1
    print('输出:我是try2')

except :
    print('输出:我是except')

else :
    print('输出:我是else')

finally :
    print('输出:我是finally')

# 输出结果:
"""
输出:我是try1
输出:我是try2
输出:我是else
输出:我是finally
"""

运行逻辑3:函数中,如果finally语句的相关代码中包含了return语句,那么该return语句所返回的值(包括空值None),将取代try,except或else语句相关代码中的返回值

因为finally中的代码块在设定上必须执行:

  • 在try中的代码块return之前,会执行finally中的语句,try中的return被忽略了,最终返回的值是finally中return值
  • try中的代码块没有return语句,执行完毕后,会继续执行else中的语句,在else中的代码块return之前,执行finally中的语句,else中的return被忽略了,最终返回的值是finally中return值
  • try中的代码块中抛出异常,被except捕获,在except中的代码块return之前,执行finally中的语句,except中的return被忽略了,最终返回的值是finally中return值
def test():
    try:
        print('输出:我是try1')
        a = 5 / 0
        print('输出:我是try2')
        return 1

    except :
        print('输出:我是except1')
        return 2
        print('输出:我是except2')

    else :
        print('输出:我是else')
        return 3

    finally :
        print('输出:finally')
        return 4

num = test()
print(num)

# 输出结果:
"""
输出:我是try1
输出:我是except1
输出:finally
4
"""


def test():
    try:
        print('输出:我是try1')
        a = 5 / 1
        print('输出:我是try2')
        return 1

    except :
        print('输出:我是except')
        return 2

    else :
        print('输出:我是else')
        return 3

    finally :
        print('输出:finally')
        return 4

num = test()
print(num)

# 输出结果:
"""
输出:我是try1
输出:我是try2
输出:finally
4
"""


def test():
    try:
        print('输出:我是try1')
        a = 5 / 1
        print('输出:我是try2')
        # return 1

    except :
        print('输出:我是except')
        return 2

    else :
        print('输出:我是else1')
        return 3
        print('输出:我是else2')

    finally :
        print('输出:finally')
        return 4

num = test()
print(num)

# 输出结果:
"""
输出:我是try1
输出:我是try2
输出:我是else1
输出:finally
4
"""

运行逻辑4:函数中,finally中不存在return,并且try中代码块没有抛出异常,那么按照 运行逻辑2,函数返回的是try或者else代码中先出现的那个return值

因为代码中程序正常运行,不一定要执行else中的代码块,如果try中return直接结束函数执行了,那么就不会执行else中的代码块

def test():
    try:
        print('输出:我是try1')
        a = 5 / 1
        print('输出:我是try2')
        return 1

    except :
        print('输出:我是except')
        return 2

    else :
        print('输出:我是else')
        return 3

    finally :   # finally中不存在return语句
        print('输出:finally')
        # return 4  

num = test()
print(num)

# 输出结果:
"""
输出:我是try1
输出:我是try2
输出:finally
1
"""


def test():
    try:
        print('输出:我是try1')
        a = 5 / 1
        print('输出:我是try2')
        # return 1

    except :
        print('输出:我是except')
        return 2

    else :
        print('输出:我是else')
        return 3

    finally :   # finally中不存在return语句
        print('输出:finally')
        # return 4  

num = test()
print(num)

# 输出结果:
"""
输出:我是try1
输出:我是try2
输出:我是else
输出:finally
3
"""

运行逻辑5:函数中,finally中不存在return,并且try中代码块产生异常,那么按照 运行逻辑1,函数返回的是except代码中的那个return值

因为代码中程序抛出异常,必须执行except中的代码块

def test():
    try:
        print('输出:我是try1')
        a = 5 / 0
        print('输出:我是try2')
        return 1

    except :
        print('输出:我是except')
        return 2

    else :
        print('输出:我是else')
        return 3

    finally :   # finally中不存在return语句
        print('输出:finally')
        # return 4  

num = test()
print(num)

# 输出结果:
"""
输出:我是try1
输出:我是except
输出:finally
2
"""

except语句

except语句的机制

每一个try语句,都必须至少有一个except语句,除非存在 finally 语句

  • 一般一个try语句后面都需要存在至少一个except语句,但是使用 finally 语句后 except 语句将成为可选的,try语句之后可以没有任何except语句
try:
	print("No Error")
	
# 抛出异常:SyntaxError: unexpected EOF while parsing

try:
	5/0
	
# 抛出异常:SyntaxError: unexpected EOF while parsing


try:
	print("No Error")

finally:
	print("Something must be done")

# 输出结果:
"""
No Error
Something must be done
"""


try:
	5/0

finally:
	print("Something must be done")

# 输出结果:
"""
Something must be done
Traceback (most recent call last):
  File "C:\编程\Python代码\test\test.py", line 3, in <module>
    5/0
ZeroDivisionError: division by zero
"""

使用 else 语句的前提是至少拥有一个 except 语句

  • 如果要使用else语句来处理没有 Python 异常被引发的情况,那么在try语句之后,必须至少存在一个except语句
try:
	print("No Error")

else:
	print("must have except")

finally:
	print("Something must be done")

# 抛出异常:SyntaxError: invalid syntax


try:
	print("No Error")

except:
	print("waiting for error")

else:
	print("must have except")

finally:
	print("Something must be done")

# 输出结果:
"""
No Error
must have except
Something must be done
"""

一个try…except语句中可以拥有多个except语句,都是最多只有一个 except 语句能与被抛出 Python 异常匹配

  • 如果try…except语句拥有多个except语句,那么与 Python 的 if 语句类似,他们会按照先后顺序进行匹配,当某一个except语句与被抛出的 Python 异常匹配时,其余的except语句将被忽略
try:
	5/0

except IndexError as e:			# 无法捕获除0异常
	print("IndexError")

except ZeroDivisionError as e:	# 可以捕获除0异常
	print("ZeroDivisionError1")

except ZeroDivisionError as e:	# 可以捕获除0异常
	print("ZeroDivisionError2")

except BaseException as e:		# 可以捕获除0异常
	print("BaseException")

# 输出结果:ZeroDivisionError1


try:
	5/0

except IndexError as e:			# 无法捕获除0异常
	print("IndexError")

except BaseException as e:		# 可以捕获除0异常
	print("BaseException")

except ZeroDivisionError as e:	# 可以捕获除0异常
	print("ZeroDivisionError1")

except ZeroDivisionError as e:	# 可以捕获除0异常
	print("ZeroDivisionError2")

# 输出结果:BaseException

except可以处理一个专门的异常,也可以处理包含在元组中的一组异常

  • 可以将多个异常类型放在一个括号中,通过逗号分隔。当try块引发其中任何一个异常时,程序都将跳转到该except块,处理这个异常
try:
	5 / 0

except (IndexError, ZeroDivisionError) as e:	# 可以捕获除0异常
	print("IndexError or ZeroDivisionError")

except BaseException as e:		# 可以捕获除0异常
	print("ZeroDivisionError1")

# 输出结果:IndexError or ZeroDivisionError

如果except后没有指定异常类型,则默认捕获所有的异常

  • 此时捕获异常范围为BaseException(后面会提到)
  • 这样的没有指定异常类型的 except 语句要求必须是最后一个 except 语句,否则程序报错
  • 原因很简单,如果它位于其他except语句之前,那么一些except语句将失去被执行的可能
try:
	5 / 0

except:	# 可以捕获所有异常
	print("捕获到异常")

# 输出结果:捕获到异常

与所有 except 语句均不匹配的 Python 异常将被重新抛出

  • 如果一个 Python 异常被引发,并且与所有的except语句均不匹配,那么该异常将作为未处理的 Python 异常被重新抛出,这可能导致整个程序因此结束执行(当然,finally中的代码块依旧会被执行)
try:
	5/0

except IndexError as e:		# 无法捕获除0异常
	print("IndexError")

except KeyError as e:		# 无法捕获除0异常
	print("KeyError")

except ValueError as e:		# 无法捕获除0异常
	print("ValueError")

finally:
	print('输出:finally')

# 抛出异常:
"""
输出:finally
Traceback (most recent call last):
  File "C:\编程\Python代码\test\main.py", line 2, in <module>
    5/0
ZeroDivisionError: division by zero
"""
在 except 语句中引用当前被处理的 Python 异常

在except语句中,使用as关键字可以指定一个与被处理异常绑定(指向异常对象)的标识符(可将其简单的视为 Python 变量),即可通过该标识符在except语句相关的代码中访问被处理的 Python 异常

此外,在 3.11 或更高版本中,通过sys模块的exception函数,同样可在except语句相关的代码中访问当前被处理的 Python 异常

  • 异常对象的常用属性
    • args:包含有关异常的错误编号和异常的描述的元组
    • strerror:异常的描述
    • errno:与异常的错误编号
try:
	open("no_exit_file.txt", "r")

except FileNotFoundError as e:	# 可以捕获除0异常
    print("异常对象:", e)
    print("异常类型:", type(e))

    # 异常对象的常用属性
    print("异常信息: ", e.args)      # 该属性返回异常的错误编号和描述
    print("异常描述: ", e.strerror)  # 该属性返回异常的描述
    print("错误号: ", e.errno)       # 该属性返回异常的错误编号

# 输出结果:
"""
异常对象: [Errno 2] No such file or directory: 'no_exit_file.txt'
异常类型: <class 'FileNotFoundError'>
异常信息:  (2, 'No such file or directory')
异常描述:  No such file or directory
错误号:  2
"""

except 语句会删除使用 as 关键字与 Python 异常绑定的标识符

  • 如果在某个except语句中使用了as关键字,那么as关键字指定的标识符,将在该except语句的相关代码执行完毕时被删除。这意味着标识符仅在except语句中保持其正确性,他不应该与同一命名空间的其他标识符重复,以避免一些不必要的错误
try:
	open("no_exit_file.txt", "r")

except FileNotFoundError as e:	# 可以捕获除0异常
    print("异常对象:", e)
    print("异常类型:", type(e))

print(e)

# 输出结果:
"""
异常对象: [Errno 2] No such file or directory: 'no_exit_file.txt'
异常类型: <class 'FileNotFoundError'>
Traceback (most recent call last):
  File "C:\编程\Python代码\test\test.py", line 9, in <module>
    print(e)
NameError: name 'e' is not defined
"""

finally语句

finally语句执行后才能抛出未被处理的异常

当try,except或else语句的相关代码引发不能被处理的 Python 异常时,这些异常不会被立即抛出,他们需要等待finally语句的相关代码的执行

try:
	5/0

except IndexError as e:		# 无法捕获除0异常
	print("IndexError")

except KeyError as e:		# 无法捕获除0异常
	print("KeyError")

except ValueError as e:		# 无法捕获除0异常
	print("ValueError")

finally:
	print('输出:finally')

# 抛出异常:
"""
输出:finally
Traceback (most recent call last):
  File "C:\编程\Python代码\test\main.py", line 2, in <module>
    5/0
ZeroDivisionError: division by zero
"""


try:
    5 / 0

except ZeroDivisionError as e:
    print("ZeroDivisionError异常被捕获")
    raise e

finally:
    print('输出:finally')
# 输出结果:
"""
ZeroDivisionError异常被捕获
输出:finally
Traceback (most recent call last):
  File "C:\编程\Python代码\test\main.py", line 6, in <module>
    raise e
  File "C:\编程\Python代码\test\main.py", line 2, in <module>
    5 / 0
ZeroDivisionError: division by zero
"""


try:
    5 / 1

except ZeroDivisionError as e:
    print("ZeroDivisionError异常被捕获")

else:
    print('输出:else')
    raise ZeroDivisionError("重新抛出的ZeroDivisionError")

finally:
    print('输出:finally')
# 输出结果:
"""
输出:else
输出:finally
Traceback (most recent call last):
  File "C:\编程\Python代码\test\main.py", line 9, in <module>
    raise ZeroDivisionError("重新抛出的ZeroDivisionError")
ZeroDivisionError: 重新抛出的ZeroDivisionError
"""
finally中执行return会导致异常丢失

如果finally语句的相关代码中包含了跳转语句,比如break,continue或return,那么这些跳转语句的执行,将导致未被except处理的 Python 异常不再被重新抛出,即便这些异常是通过raise语句主动抛出的

3.8 版本之前,在 Python 的finally语句的相关代码中,不能使用continue语句

finally中出现return语句,如果try中抛出的异常没有被捕获到,按理说当finally执行完毕后,应该被再次抛出,但finally里执行了return,导致异常被丢失,所以实际应用中,不推荐在finally中使用return返回

def test():
	try:
		5/0
		print("函数中的后续代码被执行")

	except IndexError as e:		# 无法捕获除0异常
		print("IndexError")

	except KeyError as e:		# 无法捕获除0异常
		print("KeyError")

	except ValueError as e:		# 无法捕获除0异常
		print("ValueError")

	finally:
		print('输出:finally')
		return 1

num = test()
print(num)

print("后续代码被执行")

# 输出结果:
"""
输出:finally
1
后续代码被执行
"""

raise 语句

raise 语句以及异常对象

使用 Python 提供的raise语句,开发人员可以主动抛出(引发)一个 Python 异常

raise 语句基本的语法形式为 raise <exception>
  • exception
    • 被抛出的 Python 异常对象,或 Python 异常类型如果仅给出异常类型,那么将根据该类型隐式创建其对应的实例,比如,raise ZeroDivisionError的效果等同于raise ZeroDivisionError()
raise ZeroDivisionError

# 抛出异常:
"""
Traceback (most recent call last):
  File "C:\编程\Python代码\test\main.py", line 1, in <module>
    raise ZeroDivisionError
ZeroDivisionError
"""

# 前后对比,发现效果一致
raise ZeroDivisionError()

# 抛出异常:
"""
Traceback (most recent call last):
  File "C:\编程\Python代码\test\main.py", line 1, in <module>
    raise ZeroDivisionError()
ZeroDivisionError
"""

创建异常对象时可以指定其魔法方法__str__的返回值

# 判断ZeroDivisionError()返回的东西是否为ZeroDivisionError的实例对象
ins = ZeroDivisionError()
flag = isinstance(ins, ZeroDivisionError)	
print(flag)

# 输出结果:True

ins = ZeroDivisionError()
dir(ins)	# 可以获知,该实例对象具有魔法方法__str__

# 输出结果:
"""
['__cause__', '__class__', '__context__', '__delattr__', '__dict__', '__dir__', 
'__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__',
 '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', 
 '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', 
 '__subclasshook__', '__suppress_context__', '__traceback__', 'args', 'with_traceback']
"""

# 由于调用print函数实际是执行实例对象的魔法方法__str__,打印结果为该方法返回值
# 所以可以推断出实例化异常对象时,传入的"This is a ZeroDivisionError"
# 实际就是魔法方法__str__的返回值
ins = ZeroDivisionError("This is a ZeroDivisionError")
print(ins)	

# 输出结果:This is a ZeroDivisionError


ins = ZeroDivisionError("This is a ZeroDivisionError")
describe_string = ins.__str__()		# 手动调用魔法方法__str__,打印该方法的返回值
print(describe_string)

# 输出结果:This is a ZeroDivisionError

data = 10
ins = ZeroDivisionError("This is a ZeroDivisionError, carry a data: %s" % data )
print(ins)	

# 输出结果:This is a ZeroDivisionError, carry a data: 10

在except语句中,可以使用 raise 语句,将raise语句的exception部分留空,这会将当前被处理的 Python 异常重新抛出(引发)

但是以上做法的效果并不等同于调用exception函数的语句raise sys.exception(),或类似于raise err的语句(假设err为as关键字绑定的标识符),他们会展示不同的回溯(Traceback)信息

# calculate.py文件的内容
def divide(a, b):	# 进行除法运算的函数
    return a / b

# main.py文件的内容
from calculate import divide

divide(5, 0)

# 抛出异常:
"""
Traceback (most recent call last):
  File "C:\编程\Python代码\test\main.py", line 3, in <module>
    divide(5, 0)
  File "C:\编程\Python代码\test\calculate.py", line 2, in divide
    return a / b
ZeroDivisionError: division by zero
"""


# calculate.py文件的内容
def divide(a, b):	# 进行除法运算的函数
    return a / b

# main.py文件的内容
from calculate import divide

try:
    divide(5, 0)

except ZeroDivisionError:
    print("ZeroDivisionError异常被捕获")
    raise	# 使用raise重新抛出异常
    
# 抛出异常:
"""
ZeroDivisionError异常被捕获
Traceback (most recent call last):
  File "C:\编程\Python代码\test\test.py", line 4, in <module>
    divide(5, 0)
  File "C:\编程\Python代码\test\calculate.py", line 2, in divide
    return a / b
ZeroDivisionError: division by zero
"""


# calculate.py文件的内容
def divide(a, b):	# 进行除法运算的函数
    return a / b

# main.py文件的内容
from calculate import divide

try:
    divide(5, 0)

except ZeroDivisionError as e:
    print("ZeroDivisionError异常被捕获")
    raise e	
   
# 抛出异常:
"""
ZeroDivisionError异常被捕获
Traceback (most recent call last):
  File "C:\编程\Python代码\test\test.py", line 8, in <module>
    raise e
  File "C:\编程\Python代码\test\test.py", line 4, in <module>
    divide(5, 0)
  File "C:\编程\Python代码\test\calculate.py", line 2, in divide
    return a / b
ZeroDivisionError: division by zero
"""

抛出异常时,自动创建的异常对象的魔法方法__str__的返回值即为 traceback 最后一行针对该异常的描述信息

5 / 0

# 抛出异常:
"""
Traceback (most recent call last):
  File "C:\编程\Python代码\test\main.py", line 1, in <module>
    5 / 0
ZeroDivisionError: division by zero
"""


try:
    5 / 0

except ZeroDivisionError as e:
	# 判断 e 是否为ZeroDivisionError的实例对象
    flag = isinstance(e, ZeroDivisionError)
    print(flag)
	
	# 手动调用魔法方法__str__,打印该方法的返回值,进行对比
    describe_string = e.__str__()	
    print(e)
    print(describe_string)

# 输出结果:
"""
True
division by zero
division by zero
"""


try:
    5 / 0

except ZeroDivisionError as e:
    print("自动抛出的异常被捕获")
    raise e

# 输出结果:
"""
自动抛出的异常被捕获
Traceback (most recent call last):
  File "C:\编程\Python代码\test\main.py", line 6, in <module>
    raise e
  File "C:\编程\Python代码\test\main.py", line 2, in <module>
    5 / 0
ZeroDivisionError: division by zero
"""

自行创建一个异常对象,通过raise抛出,同时携带自定义的描述信息

try:
    5 / 0

except ZeroDivisionError as e:
    print("自动抛出的异常被捕获")
    raise ZeroDivisionError("<division by zero>")

# 输出结果:
"""
自动抛出的异常被捕获
Traceback (most recent call last):
  File "C:\编程\Python代码\test\main.py", line 6, in <module>
    raise ZeroDivisionError("<division by zero>")
ZeroDivisionError: <division by zero>
"""

raise…from 语句

如果一个 Python 异常已经被某个except语句处理,而该except语句的相关代码引发了新的异常,如果新的 Python 异常是通过raise…from语句引发,那么可以为新的 Python 异常指定一个表示原因的异常,用于说明新的 Python 异常是由该异常导致的

raise…from语句可以在其他位置使用,如果位于except语句的相关代码中,那么表示原因的异常一般被指定为已被except处理的 Python 异常,此时回溯信息将优先展示表示原因的 Python 异常的信息

raisefrom 语句基本的语法形式为 raise <newexception> from <causeexception>
  • newexception

    • 被抛出的 Python 异常对象,或 Python 异常类型。如果仅给出异常类型,那么将根据该类型隐式创建其对应的实例,比如,raise RuntimeError from ValueError()的效果等同于raise RuntimeError() from ValueError()
  • causeexception

    • 表示原因的 Python 异常对象,或 Python 异常类型。如果仅给出异常类型,那么将根据该类型隐式创建其对应的实例,比如,raise RuntimeError() from ValueError的效果等同于raise RuntimeError() from ValueError()

Python 异常的基类 BaseException

在 Python 中,所有异常(表示异常的类)都需要继承自BaseException或Exception,这包括 Python 的内置异常,以及由开发人员定义的异常(当然,只有少数 Python 异常直接继承自类BaseException,大部分 Python 异常均继承自类Exception或类Exception的派生类)

在这里插入图片描述

  • Python 异常基类 BaseException 和 Exception 之间的区别
    • Exception是BaseException类的派生类,他表示不是来自于系统的非正常情况,比如,表示除数为0的 Python 异常ZeroDivisionError
    • 一般情况下,开发人员仅需要捕获从Exception类派生的各种 Python 异常,如果将捕获的范围扩大到BaseException,那么可能会导致一些意想不到的问题
    • 如果except后没有指定异常类型,则默认捕获所有的异常,即此时捕获异常范围为BaseException, 这样的没有指定异常类型的 except 语句要求必须是最后一个 except 语句,否则程序报错,原因很简单,如果它位于其他except语句之前,那么一些except语句将失去被执行的可能

如果将捕获异常的范围扩大到BaseException,可能会导致sys.exit()无法退出 Python 解释器

import sys

try:
	sys.exit()	# 尝试退出程序
except BaseException as e:
	print(f'捕获到了异常 {type(e)}')

print('sys.exit() 已经执行,但是程序没有成功退出')

# 输出结果:
"""
捕获到了异常 <class 'SystemExit'>
sys.exit() 已经执行,但是程序没有成功退出
"""

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2189946.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

集合框架02:Collection使用(1)

视频链接&#xff1a;13.05 Collection使用&#xff08;1&#xff09;_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1zD4y1Q7Fw?p5&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5 代码示例&#xff1a; package com.yundait.Demo01;import java.util.ArrayList; i…

hbuilderx+uniapp+Android健身房管理系统 微信小程序z488g

目录 项目介绍支持以下技术栈&#xff1a;具体实现截图HBuilderXuniappmysql数据库与主流编程语言java类核心代码部分展示登录的业务流程的顺序是&#xff1a;数据库设计性能分析操作可行性技术可行性系统安全性数据完整性软件测试详细视频演示源码获取方式 项目介绍 用户功能…

震撼!工业史上第一家万级别规模的工业数字化设备效果图平台

耗时八年打造&#xff0c;国内第一家万级别规模的工业数字化设备效果图平台 平台&#xff1a;www.kingview3d.cn 创作者&#xff1a;kingview3d郭工 行业&#xff1a;煤矿综合自动化、污水处理、净水处理、楼宇暖通、环保工程、医药废水处理、二供、无负压加压站、提升泵站、一…

模拟器GSN3之DHCP动态分配IP地址配置案例

前文《详解DHCP服务工作原理及配置案例》介绍了DHCP服务工作原理&#xff0c;要想彻底理解、应用DHCP服务&#xff0c;须通过实证案例学习&#xff0c;该文在GSN3虚拟环境下&#xff0c;构建DHCP服务的环境。 一、配置环境&#xff1a; 1、GSN3 2、路由器&#xff1a;R1、R2…

【微服务】服务注册与发现、分布式配置管理 - Consul(day5)

概述 作用 Consul的两大作用就是服务发现和注册与分布式配置管理。 服务发现在介绍Eureka组件的时候已经进行过详细概述&#xff0c;大概就是将硬编码到服务中的IP地址和端口号进行解耦&#xff0c;从而实现动态扩缩容、容错处理、服务管理等功能&#xff0c;通过服务注册和…

MAC备忘录空白解决方案

打开icloud->备忘录 取消勾选同步此MAC后再次勾选&#xff0c;然后点击完成即可。

<<迷雾>> 第7章 会变魔术的触发器(3)--R-S 触发器 示例电路

用来验证或非门反馈功能的完整电路 info::操作说明 如演示出现异常, 可点右侧面板的重置按钮重置 此处 R 和 S 都使用的是按钮开关 点击 R 可让 Q 熄灭 点击 S 可让 Q 亮起 primary::在线交互操作链接 https://cc.xiaogd.net/?startCircuitLinkhttps://book.xiaogd.net/cyjsjd…

针对线上消息积压的排查思路以及解决方案

一、背景 我们在日常工作中&#xff0c;经常会碰到线上告警&#xff0c;消息队列消息积压了&#xff0c;试想如果对消息的消费速率有要求的场景&#xff0c;消息积压一定会或多或少对自己本身的业务场景有影响&#xff0c;这里就针对消息积压的场景&#xff0c;谈谈具体的排查…

过滤器Filter【详解】

过滤器Filter 1、 现有问题 在以往的Servlet中&#xff0c;有冗余的代码&#xff0c;多个Servlet都有重复的代码 比如编码格式设置 登录信息认证 2、 概念 过滤器&#xff08;Filter&#xff09;是处于客户端与服务器目标资源之间的一道过滤技术。 过滤器 3、 过滤器作用 执…

Python办公自动化教程(006):Word添加标题

2.3 word标题 介绍&#xff1a; 在 python-docx 中&#xff0c;您可以使用 add_heading() 方法为文档添加标题。此方法允许您指定标题的文本和级别&#xff08;例如&#xff0c;一级标题、二级标题等&#xff09;。标题级别的范围是从 0 到 9&#xff0c;其中 0 表示文档的主标…

深度解析:从浏览器输入链接到页面展现的奇幻历程

〇、前言 当我们在浏览器中输入一个网址&#xff0c;例如&#xff1a;example.com&#xff0c;按下回车键后&#xff0c;会发生什么呢&#xff1f; 主要会发生以下这些过程&#xff1a;域名解析、建立HTTP连接、发送HTTP请求、数据传输、渲染网页、断开HTTP连接。 一、域名解…

类型转换【C++提升】(隐式转换、显式转换、自定义转换、转换构造函数、转换运算符重载......你想知道的全都有)

更多精彩内容..... &#x1f389;❤️播主の主页✨&#x1f618; Stark、-CSDN博客 本文所在专栏&#xff1a; C系列语法知识_Stark、的博客-CSDN博客 座右铭&#xff1a;梦想是一盏明灯&#xff0c;照亮我们前行的路&#xff0c;无论风雨多大&#xff0c;我们都要坚持不懈。 一…

【srm系统】供应商管理,招投标管理,电子采购系统,询价管理

前言&#xff1a; 随着互联网和数字技术的不断发展&#xff0c;企业采购管理逐渐走向数字化和智能化。数字化采购平台作为企业采购管理的新模式&#xff0c;能够提高采购效率、降低采购成本、优化供应商合作效率&#xff0c;已成为企业实现效益提升的关键手段。系统获取在文末…

[含文档+PPT+源码等]精品基于Python实现的美术馆网站的设计与实现

基于Python实现的美术馆网站&#xff0c;其设计与实现背景主要源于以下几个方面的需求和发展趋势&#xff1a; 一、文化艺术领域的发展需求 随着文化娱乐活动的日益丰富&#xff0c;美术馆作为展示艺术作品、传播文化的重要场所&#xff0c;其管理和服务模式的创新对于提升公…

LabVIEW提高开发效率技巧----使用动态事件

在LabVIEW开发过程中&#xff0c;用户交互行为可能是多样且不可预知的。为应对这些变化&#xff0c;使用动态事件是一种有效的策略。本文将从多个角度详细介绍动态事件的概念及其在LabVIEW开发中的应用技巧&#xff0c;并结合实际案例&#xff0c;说明如何通过动态事件提高程序…

【售后资料】软件售后服务方案(word原件)

软件售后服务方案的售后服务范围广泛&#xff0c;涵盖了多个方面&#xff0c;以确保客户在使用软件过程中得到全面、及时的支持。具体来说&#xff0c;这些服务范围通常包括以下几个核心内容&#xff1a; 技术支持服务维护与更新服务培训与教育服务定制化服务数据管理与服务客户…

如何获取网页内嵌入的视频?

如何获取网页内嵌入的视频&#xff1f; 有时插件无法识别的视频资源&#xff0c;可以通过手动使用浏览器的开发者工具来抓取。你可以按照以下步骤操作&#xff1a; 步骤&#xff1a; 打开网页并按 F12&#xff1a;在视频页面按下 F12 或右键点击网页并选择“检查”或“Inspe…

Spring Boot实现的大学生就业市场解决方案

1系统概述 1.1 研究背景 如今互联网高速发展&#xff0c;网络遍布全球&#xff0c;通过互联网发布的消息能快而方便的传播到世界每个角落&#xff0c;并且互联网上能传播的信息也很广&#xff0c;比如文字、图片、声音、视频等。从而&#xff0c;这种种好处使得互联网成了信息传…

【案例】距离限制模型透明

开发平台&#xff1a;Unity 2023 开发工具&#xff1a;Unity ShaderGraph   一、效果展示 二、路线图 三、案例分析 核心思路&#xff1a;计算算式&#xff1a;透明值 实际距离 / 最大距离 &#xff08;实际距离 ≤ 最大距离&#xff09;   3.1 说明 | 改变 Alpha 值 在 …

简易投影仪的制作

今天不做开发类的文章&#xff0c;来给大家整个活哈哈哈哈哈。由于前几天室友说看小屏幕的抖音太不舒服&#xff0c;比较累眼睛&#xff0c;所以我萌生出来一个制作投影仪的想法。于是查阅了资料最终完成以下的设计。 以下设计价格最高的是一部旧的可拆卸的智能手机 简易投影仪…