Python异常处理

系统 271 0

在编写计算机程序时,通常能够区分正常和异常(不正常)情况。异常事件可能是错误(如试图除以零),也可能是通常不会发生的事情。Python使用异常对象来表示异常状态,并在遇到错误时引发异常。异常对象未被处理(或捕获)时,程序将终止并显示一条错误消息(traceback)。

            
              #试图除以零的报错
print(1/0)
# Traceback (most recent call last):
#     print(1/0)
#     ZeroDivisionError: division by zero
            
          

正如你所见,出现问题是,自动引发异常。要引发异常,可使用raise语句,并将一个类(必须是Exception的子类)或者实例作为参数,将类作为参数时,将自动创建一个实例。

            
              raise Exception
# Traceback (most recent call last):
#     raise Exception
# Exception
raise Exception("error occurred ")
# Traceback (most recent call last):
#     raise Exception("error occurred ")
# Exception: error occurred 
            
          

在第一个示例(raise Exception)中,引发的时通常异常,并没有指出来出现了什么错误。在第二个示例中,添加了错误消息error occurred。 几乎所有的异常类都是由Exception派生出来的。

常见类名 描述
KeyboardInterrupt 用户中断执行(通常是输入Ctrl+C)
ArithmeticError 引用属性或给它赋值失败时引发
ZeroDivisionError 在除法或求模运算的第二个参数为零时引发
ImportError 导入模块/对象失败
IndexError 序列中没有此索引(index)
TypeError 将内置操作或函数用于类型不正确的对象时引发

 

  • 捕获异常

在编写代码的时候,出现异常可以对其进行一定的处理,而在处理之前,我们通常要对其进行捕获,称之为 捕获异常 。可以使用try/except语句。(此时还是以ZeroDivisionError为例,演示如何捕获异常)

            
              
x = float(input("Enter the first number:"))     #用户输入的内容为str型,需对其进行强转,int或者float均可
y = float(input("Enter the second number:"))
print(x/y)
# Traceback (most recent call last):
#     print(x/y)
# ZeroDivisionError: float division by zero
print(x%y)
# Traceback (most recent call last):
#     print(x%y)
# ZeroDivisionError: float modulo
            
          

这个程序运行正常,直到用户在第二个参数输入0,对于第二个参数输入值为0这种异常状态时,使用try/except进行捕获异常(这里打印一条对用户更友好的错误消息)。

            
              try:
    x = float(input("Enter the first number:"))
    y = float(input("Enter the second number:"))
    print(x/y)
except:
    print("The sceond number can't be zero!")
    
"""
Enter the first number:1
Enter the second number:0
The sceond number can't be zero!
"""
            
          

或许使用if来判断y值好像简单许多,就本例而言,这可能也是更佳的解决方案,因为这个程序执行的除法运算越多,则每条除法运算都需要一条if进行判断,无疑增加其空间复杂度(O(n)),而使用try/except只需要一个错误处理程序。

发生除零行为时,如果启用了“抑制”功能,将返回None,换言之,如果启用“抑制”功能,将不应依赖返回值。关闭“抑制”功能时,捕获异常ZeroDivisionError

            
              class MuffledCalculator:
    muffled = False     # 抑制
    def calc(self,expr):
        try:
            return eval(expr)
        except ZeroDivisionError:
            if self.muffled:
                print('Division by zero is illegal')
            else:
                raise
# eval() 函数用来执行一个字符串表达式,并返回表达式的值。

c = MuffledCalculator()
print(c.calc('10/2'))
# 5.0
print(c.calc('10/0'))   #关闭抑制,报错
# ZeroDivisionError: division by zero
c.muffled = True
print(c.calc('10/0'))
# Division by zero is illegal
# None
            
          

如果无法处理异常,在except子句中使用不带参数的raise通常是不错的选择,有时你可能想引发别的异常,在这种情况下,导致进入except子句的异常将作为异常上下文储存起来,并出现在最终的错误消息中。

  • 证明except在处理异常优于if

            
              x = float(input("Enter the first number:"))
y = float(input("Enter the second number:"))
print(x/y)

"""
Enter the first number:10
Enter the second number:python
ValueError: could not convert string to float: 'python'
"""
            
          

对于这种情况,用户在第二个参数输入的为字符串或者其他类型的数据,此时使用if来判断还是最优的解吗?对于任何可能出现的异常进行判断和捕获。

            
              try:
    x = float(input("Enter the first number:"))
    y = float(input("Enter the second number:"))
    print(x/y)
except ZeroDivisionError:
    print("The sceond number can't be zero!")
except TypeError:
    print("Please change a data type")
except ValueError:
    print("That wasn't a number,was it?")
            
          

仅当有异常时才会中断输入

            
              while True:
    try:
        x = float(input("Enter the first number:"))
        y = float(input("Enter the second number:"))
        print(x / y)
    except:
        print("Invalid input,Please try again")
        break
            
          

仅当没有引发异常时,才会跳出循环,只要出现错误,程序就会要求用户提供新的输入

            
              while True:
    try:
        x = float(input("Enter the first number:"))
        y = float(input("Enter the second number:"))
        print(x / y)
    except:
        print("Invalid input,Please try again")
    else:
        break


"""
Enter the first number:a
Invalid input,Please try again
Enter the first number:1
Enter the second number:0
Invalid input,Please try again
Enter the first number:10
Enter the second number:2
5.0
"""
            
          
  • finally的用法

            
              '''
try:
    执行代码
except:
    如果有异常发生,执行此处的代码
else:
    如果没有异常发生,执行此处代码
finally:                                         
    不管有没有异常都会执行此处代码
'''
            
          
  • 自定义异常类

自定义的异常类必须是Exception或者Error的子类!!!

            
              class My_Exception(Exception):
    '''
    Custom exception types
    '''
    def __init__(self, parameter, para_value):
        my_error = 'The parameter "{0}" is not legal:{1}'.format(parameter, para_value)
        Exception.__init__(self, my_error)
        self.parameter = parameter
        self.para_value = para_value
            
          

对于warnings警告模块,最后结尾说两句:

            
              import warnings
warnings.warn("I've got a bad feeling about this.")

# warnings.filters()      用于过滤警告
# warnings.warn             用于发出警告
            
          
  • 小结:

  • 异常对象:异常情况时用异常对象表示的。对于异常情况,有多种处理方式;如果忽略,将导致程序终止。
  • 引发异常:可使用raise语句来引发异常,它将一个异常类或者异常实例作为参数,也可以使用excerpt同时判断多个异常情况(上面有示例)。如果在except子句中调用raise时没有提供任何参数,它将重新引发该子句捕获异常。
  • 自定义的异常类:通过Exception派生出来的自定义异常类
  • 捕获异常:要捕获异常,可在try语句中使用except子句,在except子句中,如果没有指定异常类,将捕获所有的异常。也可以指定多个异常类,将其放在 元组 中。

  • else子句:除except子句外,还可以使用else子句,在主try块没有引发异常时执行。

  • finally子句:确保代码块无论怎么样都可以执行异常,可以用try/finally,将代码块放在finally子句中。

  • 警告:警告类似于异常,但是通常只打印一条错误消息,可以指定警告类别,因为它们是 Warning 的子类。

按照我的python版本找到了关于warning的文档。需要请参考!

Warning文档

 


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请请扫描上面二维码支持博主1元、2元、5元等您想捐的金额吧,狠狠点击下面给点支持吧

发表我的评论
最新评论 总共0条评论