python基础(8):python异常

一、异常

1.定义

Python使用异常对象来表示异常状态,并在遇到错误时引发异常。异常对象未被处理(或捕获)时,程序将终止并显示一条错误消息(traceback)。

>>> 1 / 0 
Traceback (most recent call last): 
 File "<stdin>", line 1, in ? 
ZeroDivisionError: integer division or modulo by zero

2.自定义异常

class SomeCustomException(Exception): pass

3.自主引发异常与自定义异常信息——raise语句

>>> raise Exception  # 自主引发异常,你也可以引发ZeroDivisionError等
Traceback (most recent call last): 
 File "<stdin>", line 1, in ? 
Exception 

>>> raise Exception('hyperdrive overload')   # 引发异常,并自定义异常信息
Traceback (most recent call last): 
 File "<stdin>", line 1, in ? 
Exception: hyperdrive overload   # 结果显示自定义异常信息

4.捕获异常

1)在捕捉到异常的同时,引发另一个异常:

注意:

  1. 捕捉到一个异常的时候,同时引发另一个异常,导致进入except子句的异常将被作为异常上下文存储起来,然后报错信息将会出现两个异常的错误信息:

    >>> try:
    ...    1/0
    ... except ZeroDivisionError:
    ...    raise ValueError
    ...
    Traceback (most recent call last):
      File "<stdin>", line 2, in <module>
    ZeroDivisionError: division by zero
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "<stdin>", line 4, in <module>
    ValueError
    
  2. 若你想要去掉except子句的异常报错的话:

    >>> try:
    ...    1/0
    ... except ZeroDivisionError:
    ...    raise ValueError from None
    ...
    Traceback (most recent call last):
      File "<stdin>", line 4, in <module>
    ValueError
    

2)捕捉多个异常

        运行代码的时候,有时候不只出现一个异常,所以需要多个异常处理。
        如:

>>> try:
...  	x = int(input('Enter the first number: '))
...  	y = int(input('Enter the second number: '))
...  	print(x / y)
... except ZeroDivisionError:
...  	print("The second number can't be zero!")
...
Enter the first number: 10
Enter the second number: "Hello,world!"
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
ValueError: invalid literal for int() with base 10: '"Hello,world!"'

        上例中,可以看出,在捕捉处理了ZeroDivisionError之后,出现了新的异常,所以针对这种异常,也需要使用except子句进行处理。

i)多次捕捉,分别处理——多个except子句
>>> try:
...  	x = int(input('Enter the first number: '))
...  	y = int(input('Enter the second number: '))
...  	print(x / y)
... except ZeroDivisionError:
...  	print("The second number can't be zero!")
... except ValueError:
...  	print("That wasn't a number,was it?")
...
Enter the first number: 10
Enter the second number: "Hello,world!"
That wasn't a number,was it?
ii)一次捕捉,一次处理——一个except子句

1.相同处理:打印相同信息

>>> try:
...  	x = int(input('Enter the first number: '))
...  	y = int(input('Enter the second number: '))
...  	print(x/y)
... except(ZeroDivisionError,TypeError,NameError,ValueError):
...  	raise   #可以使用print("xxxx") 无论什么错误,都输出同一句话
...
Enter the first number: 10
Enter the second number: 0
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
ZeroDivisionError: division by zero

2.不同处理:打印对应的错误信息

>>> try:
...  	x = int(input('Enter the first number: '))
...  	y = int(input('Enter the second number: '))
...  	print(x/y)
... except(ZeroDivisionError,ValueError) as e:
...  	print(e)
...
Enter the first number: 10
Enter the second number: 0
division by zero

Enter the first number: 10
Enter the second number: "Hello,world!"
invalid literal for int() with base 10: '"Hello,world!"'
iii)一次捕捉所有的异常

以上的两种方式,捕捉的异常都可能不全,这种方法捕捉全部异常。

while True: 
 	try: 
 		x = int(input('Enter the first number: ')) 
 		y = int(input('Enter the second number: ')) 
 		value = x / y 
 		print('x / y is', value) 
 	except: 
 		print('Invalid input. Please try again.') 
 	else: 
 		break

try:... except:... ” 捕获所有的异常很危险:

  • 会隐藏你有心理准备的错误信息。
  • 隐藏你没有考虑过的错误。
  • 捕获不是从Exception派生的异常
           其中包括SystemExit和KeyboardInterrupt(从BaseException——Exception的超类 派生而来的异常,例如:用户使用Ctrl + C终止执行的企图、调用函数sys.exit来终止执行的企图等)。

在大多数情况下,更好的选择是使用except Exception as e并对异常对象进行检查,以免捕捉到无需捕捉的异常。

>>> while True:
...    try:
...       x = int(input('Enter the first number: '))
...       y = int(input('Enter the second number: '))
...       value=x/y
...       print('x / y is',value)
...    except Exception as e:
...       print('Invalid input:',e)
...       print('Please try again')
...    else:
...       break
...
Enter the first number: 1
Enter the second number: 0
Invalid input: division by zero
Please try again

Enter the first number: 10
Enter the second number: "Hello,world!"
Invalid input: invalid literal for int() with base 10: '"Hello,world!"'
Please try again

Enter the first number: 1
Enter the second number:
Invalid input: invalid literal for int() with base 10: ''
Please try again

Enter the first number: 'x'
Invalid input: invalid literal for int() with base 10: "'x'"
Please try again

Enter the first number: quuux
Invalid input: invalid literal for int() with base 10: 'quuux'
Please try again

Enter the first number: 10
Enter the second number: 2
x / y is 5.0

3)语句

 try.. except...[else...][finally...]

注意:

  1. else :
    当没有引发异常的时候,不会进入except内,而是执行else内的代码。
  2. finally :
    try子句执行完毕后:
        i)若存在except子句和else子句,则先执行,最后执行finally子句。
        ii)若不存在,则直接进入finally子句。
  3. 通常finally可用于在发生异常时执行清理工作:
>>> x=None  # ZeroDivisionError将导致根本没有机会给它赋值,进而导致在finally子句中对其执行del时引发未捕获的异常。
>>> try:      
...    x=1/0
... finally:
...    print('Cleaning up...')
...    del x
...
Cleaning up...    
Traceback (most recent call last):    #在清理工作结束后才崩溃
  File "<stdin>", line 2, in <module>
ZeroDivisionError: division by zero

5.函数调用与异常

如果函数A将引发异常,而函数B调用了函数A,函数C调用了函数B,那么:报错信息(函数C → 函数B → 函数A)

>>> def faulty(): 
... raise Exception('Something is wrong') 
... 
>>> def ignore_exception(): 
... faulty() 
... 
>>> def handle_exception(): 
... try: 
... faulty() 
... except: 
... print('Exception handled') 
... 
>>> ignore_exception() 
Traceback (most recent call last): 
 File '<stdin>', line 1, in ? 
 File '<stdin>', line 2, in ignore_exception #最外层函数报错:错误处在调用faulty的地方
 File '<stdin>', line 2, in faulty   #最内层函数报错
Exception: Something is wrong 
>>> handle_exception() 
Exception handled

6.不那么异常的情况——警告

Tips

  1. 如果你只想发出警告,指出情况偏离了正轨,可使用模块warnings中的函数warn。
  2. 警告只显示一次。如果再次运行最后一行代码,什么事情都不会发生。

1)指定警告类别

>>> from warnings import filterwarnings
>>> from warnings import warn

# 将警告设置为ignore,则会自动忽略此条警告
>>> filterwarnings("ignore")
>>> warn("This is a warn that I hope you ignore")
>>> warn("ignore2")

# 将警告设置为error,则会引发异常,其信息为你所设置的内容
>>> filterwarnings("error")
>>> warn("This is a warn who will be a exception")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UserWarning: This is a warn who will be a exception

>>> warn("exception2")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UserWarning: exception2

2)不指定警告类别

>>> from warnings import warn
>>> warn("I've got a bad feeling about this.")
__main__:1: UserWarning: I've got a bad feeling about this.

[ 参考文档 ]

  • [挪]-Magnus-Lie-Hetland-Python基础教程(第3版)
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值