Python异常处理

软件程序在运行过程中,非常可能出现异常,比如:程序在运行中,突然内存或硬盘满了;为了增加程序的健壮性,在遇到意外情况(出现异常)时让程序做出合理的处理,在编写程序时需要考虑如何处理异常情况。

异常机制本质:当程序出现异常,程序安全的退出,处理完后继续执行的机制。

python中一切都是对象,异常也采用对象的方式来处理。处理过程:

1、抛出异常:在执行一个方法时,如果发生异常,则这个方法生成代表该异常的一个对象,停止当前执行路径,并把异常对象提交给解释器。

2、捕获异常:解释器得到该异常后,寻找相应的代码来处理该异常。 

异常的示例

下面代码首先从控制台读取字符串,并将字符串转化为 int 数据类型,接着打印输入的数字,并将打印5除以该数字。当输入数字 0 程序会发生错误 ZeroDivisionError: division by zero ,输入字符串时程序会发生错误 ValueError 。

示例代码如下

i = int(input("请输入数字:"))
print(i)
print(5/i)

代码运行结果

示例代码如下(该程序只有当输入数字 66 时程序才会退出,否则将一直执行,且当输入的不是数字时会打印异常信息)

while True:
    try:
        x = int(input("请输入一个数字(输入66时程序退出):"))
        print("输入的数字是:",x)
        if x == 66:
            print("程序退出")
            break
    except Exception as e:
        print("异常,输入的不是数字!")
        print(e)

代码运行结果

请输入一个数字(输入66时程序退出):88
输入的数字是: 88
请输入一个数字(输入66时程序退出):CSDN
异常,输入的不是数字!
invalid literal for int() with base 10: 'CSDN'
请输入一个数字(输入66时程序退出):
异常,输入的不是数字!
invalid literal for int() with base 10: ''
请输入一个数字(输入66时程序退出):66
输入的数字是: 66
程序退出

异常类继承层次

BaseException    # 所有异常的基类
 +-- SystemExit    # 解释器请求退出
 +-- KeyboardInterrupt     用户中断执行(通常是输入^C)
 +-- GeneratorExit    # 生成器(generator)发生异常来通知退出
 +-- Exception    # 常规异常的基类
      +-- StopIteration    # 迭代器没有更多的值
      +-- StandardError    # 标准错误
      |    +-- BufferError
      |    +-- ArithmeticError
      |    |    +-- FloatingPointError
      |    |    +-- OverflowError
      |    |    +-- ZeroDivisionError
      |    +-- AssertionError
      |    +-- AttributeError
      |    +-- EnvironmentError
      |    |    +-- IOError
      |    |    +-- OSError
      |    |         +-- WindowsError (Windows)
      |    |         +-- VMSError (VMS)
      |    +-- EOFError
      |    +-- ImportError
      |    +-- LookupError
      |    |    +-- IndexError
      |    |    +-- KeyError
      |    +-- MemoryError
      |    +-- NameError
      |    |    +-- UnboundLocalError
      |    +-- ReferenceError
      |    +-- RuntimeError
      |    |    +-- NotImplementedError
      |    +-- SyntaxError
      |    |    +-- IndentationError
      |    |         +-- TabError
      |    +-- SystemError
      |    +-- TypeError
      |    +-- ValueError
      |         +-- UnicodeError
      |              +-- UnicodeDecodeError
      |              +-- UnicodeEncodeError
      |              +-- UnicodeTranslateError
      +-- Warning
           +-- DeprecationWarning
           +-- PendingDeprecationWarning
           +-- RuntimeWarning
           +-- SyntaxWarning
           +-- UserWarning
           +-- FutureWarnin
           +-- ImportWarnin
           +-- UnicodeWarnin
           +-- BytesWarning

从异常类的继承层次可见,异常根类是 BaseException ,它的子类很多,其中 Exception 是非系统退出的异常,他包含了很多常用异常。如果自定义异常需要继承 Exception 及其子类,不要直接继承 BaseException 。此外,还有一类异常是 Warning ,他表示“警告”,提示程序潜在问题。

常见异常

AttributeError异常

该异常表示试图访问一个类中不存在的成员(包括:成员变量、属性和成员方法)而引发的异常。

示例代码如下

class Animal:
    pass
a = Animal()
print(a.run())

代码运行结果

Traceback (most recent call last):
  File "D:\creation\PythonStudy\Pythonproject\mypro01\mypy01.py", line 4, in <module>
    print(a.run())
          ^^^^^
AttributeError: 'Animal' object has no attribute 'run'

OSError异常

OSError 是操作系统相关异常。Python3.3版本后 IOError (输入输出异常)也并入OSError 异常,所以输入输出异常也属于 OSError 异常。例如:“未找到文件”或“磁盘已满”异常。

示例代码如下

f = open("OSError.txt")
# 当前目录下不存在该文件,会抛出FileNotFoundErrory异常

代码运行结果

Traceback (most recent call last):
  File "D:\creation\PythonStudy\Pythonproject\mypro01\mypy01.py", line 1, in <module>
    f = open("OSError.txt")
        ^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: 'OSError.txt'

IndexError异常

IndexError 异常是访问序列元素时,下标索引超出取值范围所引起的异常。

示例代码如下

a = ["邂","逅","自","己"]
print(a[4])

代码运行结果

Traceback (most recent call last):
  File "D:\creation\PythonStudy\Pythonproject\mypro01\mypy01.py", line 2, in <module>
    print(a[4])
          ~^^^
IndexError: list index out of range

KeyError异常

该异常是由于试图访问字典里不存在的键而引发的异常。

示例代码如下

a = {"name":"邂逅自己","age":18,"school":"primary"}
print(a["name"]) # 输出 邂逅自己
print(a[100]) #没有该键

代码运行结果

Traceback (most recent call last):
  File "D:\creation\PythonStudy\Pythonproject\mypro01\mypy01.py", line 3, in <module>
    print(a[100]) #没有该键
          ~^^^^^
KeyError: 100
邂逅自己

NameError异常

该异常是试图使用一个不存在的变量而引发的异常。

输入下面代码

a = {"name":"邂逅自己","age":18,"school":"primary"}
print(a[name])

代码运行如下

Traceback (most recent call last):
  File "D:\creation\PythonStudy\Pythonproject\mypro01\mypy01.py", line 2, in <module>
    print(a[name])
            ^^^^
NameError: name 'name' is not defined

注意:如果之前没有创建过变量 a ,使用 a = 10 代码则不会引发异常,因为赋值时,如果变量不存在就会创建它,所以不会引发异常。

TypeError异常

该异常是试图传入与所需数据类型不同的变量引起的。

示例代码如下

i = '6' #i为str类型,下面需要的是整数类型
print(5/i)

代码运行结果

Traceback (most recent call last):
  File "D:\creation\PythonStudy\Pythonproject\mypro01\mypy01.py", line 2, in <module>
    print(5/i)
          ~^~
TypeError: unsupported operand type(s) for /: 'int' and 'str'

ValueError异常

该异常是由传入一个无效的参数值而引发的异常。 

示例代码如下

i = 'CSDN'
print(5/int(i))

代码运行结果

Traceback (most recent call last):
  File "D:\creation\PythonStudy\Pythonproject\mypro01\mypy01.py", line 2, in <module>
    print(5/int(i))
            ^^^^^^
ValueError: invalid literal for int() with base 10: 'CSDN'

SyntaxError异常

该异常是由语法错误引起的

示例代码如下

int a = 3
print(a)

代码运行结果

  File "D:\creation\PythonStudy\Pythonproject\mypro01\mypy01.py", line 1
    int a = 3
        ^
SyntaxError: invalid syntax

Process finished with exit code 1

常见异常汇总

异常名称说明
ArithmeticError所有数值计算错误的基类
AssertionError断言语句失败
AttributeError对象没有这个属性
BaseException所有异常的基类
DeprecationWarning关于被弃用的特征的警告
EnvironmentError操作系统错误的基类
EOFError没有内建输入,到达EOF标记
Exception常规错误的基类
FloatingPointError浮点计算错误
FutureWarning关于构造将来语义会有改变的警告
GeneratorExit生成器(generator)发生异常来通知退出
ImportError导入模块/对象失败
IndentationError缩进错误
IndexError序列中没有此索引(index)
IOError输入/输出操作失败
KeyboardInterrupt用户中断执行(通常是输入^C)
KeyError映射中没有这个键
LookupError无效数据查询的基类
MemoryError内存溢出错误(对于Python解释器不是致命的)
NameError未声明/初始化对象(没有属性)
NotImplementedError尚未实现的方法
OSError操作系统错误
OverflowError数值运算超出最大限制
PendingDeprecationWarning关于特性将会被弃用的警告
ReferenceError弱引用(Weak referencce)试图访问已经垃圾回收了的对象
RuntimeError一般的运行时错误
RuntimeWarning可疑的运行时行为(runtime behavior)的警告
StandardError所有的内建标准异常的基类
StopIteration迭代器没有更多的值
SyntaxErrorPython语法错误
SyntaxWarning可疑的语法的警告
SystemError一般的解释器系统错误
SystemExit解释器请求退出
TabErrorTab和空格混用
TypeError对类型无效的操作
UnboundLocalError访问未初始化的本地变量
UnicodeDecodeErrorUnicode解码时的错误
UnicodeEncodeErrorUnicode编码时错误
UnicodeErrorUnicode相关的错误
UnicodeTranslateErrorUnicode转换时错误警告
UserWarning用户代码生成的警告
ValueError传入无效的参数
Warning警告的基类
WindowsError系统调用失败
ZeroDivisionError除(或取模)零(所有数据类型)

捕获异常

try-except语句

当出现异常时,若当前函数有能力解决,则捕获异常进行处理;若没有能力解决,则抛给上层调用者(函数)处理。如果上层调用者仍然无法处理,则继续抛它的上层调用者;直到有能力处理它。若所有函数都没有处理该异常,那么Python解释器会终止程序运行。

基本格式:

try:
    被监控可能引发异常的语句块
except Exception [as e]:
    异常处理语句块
  1. try 块包含着可能引发异常的代码,except用来捕捉和处理发生的异常
  2. 执行时若 try 块中没有引发异常,则会跳过 except 继续执行后面的代码
  3. 执行的时候,如果 try 块中发生了异常,则跳过 try 块中的后续代码,跳到相应的 except 块中处理异常;异常处理完后,继续执行后面的代码

输入下面代码

import datetime as dt # 导入Python内置的datetime日期时间模块,并将其命名为dt

def read_date(in_date): # 定义函数,将传入的字符串转换为日期,并进行格式化
    try:
        date = dt.datetime.strptime(in_date,'%Y-%m-%d')
        return date
    except ValueError as e: # 捕获ValueError异常
        print('发生了 ValueError 异常')
        print(e) # 获取异常对象

str_date = '2020-B-18'# 此处为无效日期,有效日期如 2020-8-18
print('日期 = {0}'.format(read_date(str_date)))

代码运行结果

发生了 ValueError 异常
time data '2020-B-18' does not match format '%Y-%m-%d'
日期 = None

 多个 except 代码块

如果 try 代码块中有很多语句抛出异常,而且抛出异常的种类很多,那么可以在 try 后面跟多个except代码块。其语法格式如下:

try:
    <可能会抛出异常的语句>
except[异常类型1]:
    <处理异常>
except[异常类型2]:
    <处理异常>
...
except[异常类型n]:
    <处理异常>
    

注意:当捕获多个异常类之间存在父子关系时,捕获异常顺序与 except 代码块的顺序有关。从上到下先捕获子类,后捕获父类,否则子类捕获不到。 

示例代码如下

import datetime as dt

def read_date_file(filename):
    try:
        file = open(filename) # open函数从文件中读取字符串
        in_date = file.read()
        in_date =  in_date.strip() # 剔除字符串前后空白字符(包括空格、制表符、换行和回车等字符)
        date = dt.datetime.strptime(in_date,'%Y-%m-%d')
        return date
    except ValueError as e:
        print(e)
    except FileNotFoundError as e:
        print(e)
    except OSError as e:
        print(e)

date = read_date_file('file.txt')
print('日期 = {0}'.format(date))

代码运行结果

[Errno 2] No such file or directory: 'file.txt'
日期 = None

上面代码需要注意 FileNotFoundError 与 OSError 不能调换位置,否则 except FileNotFoundError as e 代码块永远不会进入。

try-except语句嵌套

Python中 try-except 语句可以任意嵌套,不仅可以嵌套在 try 语句中,也可以嵌套在 except 代码块或 finally 代码块。try-except 代码块会使程序流程变得复杂,如果能用多 except 捕获的异常,尽量不要使用 try-except 嵌套。

示例代码如下(代码中通过捕获 ValueError 异常的 try-catch 语句嵌套在 FileNotFoundError 和 OSError 异常的 try-catch 语句中)

import datetime as dt

def read_date_file(filename):
    try:
        file = open(filename)
        try:
            in_date = file.read()
            in_date =  in_date.strip() # 剔除字符串前后空白字符(包括空格、制表符、换行和回车等字符)
            date = dt.datetime.strptime(in_date,'%Y-%m-%d')
            return date
        except ValueError as e:
            print(e)
    except FileNotFoundError as e:
        print(e)
    except OSError as e:
        print(e)

date = read_date_file('file.txt')
print('日期 = {0}'.format(date))

多重异常捕获 

对于多个不同类型的异常,要求捕获之后的处理都是调用同一方法时,可以把这些异常都放到一个元组中,这样可以大大简化代码。

示例代码如下

import datetime as dt

def read_date_file(filename):
    try:
        file = open(filename) # open函数从文件中读取字符串
        in_date = file.read()
        in_date =  in_date.strip() # 剔除字符串前后空白字符(包括空格、制表符、换行和回车等字符)
        date = dt.datetime.strptime(in_date,'%Y-%m-%d')
        return date
    except (ValueError,OSError) as e: # 多重异常捕获
        print(e)

date = read_date_file('file.txt')
print('日期 = {0}'.format(date))
  • 28
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

邂逅自己

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值