第14章 异常处理

14.1 一个异常示例

ZeroDivisionError异常:除0异常,因为在数学上除数不能为0。

ValueError异常:因为输入的是字符串。

14.2 异常类继承层次 

 Python中异常根类是BaseException。异常类继承层次如下:

BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StopAsyncIteration
      +-- ArithmeticError
      |    +-- FloatingPointError
      |    +-- OverflowError
      |    +-- ZeroDivisionError
      +-- AssertionError
      +-- AttributeError
      +-- BufferError
      +-- EOFError
      +-- ImportError
      |    +-- ModuleNotFoundError
      +-- LookupError
      |    +-- IndexError
      |    +-- KeyError
      +-- MemoryError
      +-- NameError
      |    +-- UnboundLocalError
      +-- OSError
      |    +-- BlockingIOError
      |    +-- ChildProcessError
      |    +-- ConnectionError
      |    |    +-- BrokenPipeError
      |    |    +-- ConnectionAbortedError
      |    |    +-- ConnectionRefusedError
      |    |    +-- ConnectionResetError
      |    +-- FileExistsError
      |    +-- FileNotFoundError
      |    +-- InterruptedError
      |    +-- IsADirectoryError
      |    +-- NotADirectoryError
      |    +-- PermissionError
      |    +-- ProcessLookupError
      |    +-- TimeoutError
      +-- ReferenceError
      +-- RuntimeError
      |    +-- NotImplementedError
      |    +-- RecursionError
      +-- SyntaxError
      |    +-- IndentationError
      |         +-- TabError
      +-- SystemError
      +-- TypeError
      +-- ValueError
      |    +-- UnicodeError
      |         +-- UnicodeDecodeError
      |         +-- UnicodeEncodeError
      |         +-- UnicodeTranslateError
      +-- Warning
           +-- DeprecationWarning
           +-- PendingDeprecationWarning
           +-- RuntimeWarning
           +-- SyntaxWarning
           +-- UserWarning
           +-- FutureWarning
           +-- ImportWarning
           +-- UnicodeWarning
           +-- BytesWarning
           +-- ResourceWarning

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

提示:Python的异常类命名主要有Exception、Error和Warning。有时翻译为“错误”或“异常”,统一为异常。

14.3 常见异常

 14.3.1 AttributeError异常

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

 14.3.2 OSError异常

OSError是操作系统相关异常。Python3.3版本后IOError(输入输出异常)也并入OSError异常。

例如,未找到文件或磁盘已满。

 FileNotFoundError属于OSError异常。

14.3.3 Indexerror异常

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

14.3.4 KeyError异常 

 KeyError异常是试图访问字典里不存在的键时而引发的异常。

14.3.5 NameError异常

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

赋值时,如果变量不存在就会创建,不会发生异常。

14.3.6 TypeError异常 

 TypeError是试图传入变量类型与要求的不符合时而引发的异常。

14.3.7 ValueError异常 

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

14.4 捕获异常

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

14.4.1 try-except语句

 捕获异常是通过try-except语句实现的。最基本的语法:

try:

        <可能会抛出异常的语句>

except        [异常类型]:

        <处理异常>

import datetime as dt

def read_date(in_date):
    try:
        date = dt.datetime.strptime(in_date, '%Y-%m-%d')    # 可能会抛出ValueError异常
        return date
    except ValueError:
        print('处理ValueError异常')
        
str_date = '2020-B-18'  # '2020-B-18'
print('日期 = {0}'.format(read_date(str_date)))

datetime是Python内置的时间模块 

 还需要获得异常对象。

import datetime as dt

def read_date(in_date):
    try:
        date = dt.datetime.strptime(in_date, '%Y-%m-%d')    # 可能会抛出ValueError异常
        return date
    except ValueError as e:
        print('处理ValueError异常') #e是异常对象,print(e)指令可以打印异常对象,打印异常对象会输出描述异常对象的信息
        print(e)

str_date = '2020-B-18'  # '2020-B-18'
print('日期 = {0}'.format(read_date(str_date)))

14.4.2 多个except代码块 

try:

        <可能会抛出异常的语句>

except        [异常类型1]:

        <处理异常>

except        [异常类型2]:

        <处理异常>

....

except        [异常类型n]:

        <处理异常>

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

OSError是FileNotFoundError的父类,如果代码FileNotFoundError在后面,那么
FileNotFoundError永远不会进入。
import datetime as dt


def read_date_from_file(filename):
    try:
        file = open(filename)
        in_date = file.read()
        in_date = in_date.strip()   # in_date.strip()提出字符串前后空白字符(包括空格、制表符、换行和回车等字符)
        date = dt.datetime.strptime(in_date, '%Y-%m-%d')    # 从文件中读字符串并解析为日期
        return date
    except ValueError as e:
        print('处理ValueError异常')
        print(e)
    except FileNotFoundError as e:
        print('处理FileNotFoundError异常')
        print(e)
    except OSError as e:
        print('处理OSError异常')
        print(e)


date = read_date_from_file('readme.txt')
print('日期 = {0}'.format(date))

14.4.3 try-except语句嵌套

import datetime as dt


def read_date_from_file(filename):
    try:
        file = open(filename)
        try:
            in_date = file.read()
            in_date = in_date.strip()   # in_date.strip()提出字符串前后空白字符(包括空格、制表符、换行和回车等字符)
            date = dt.datetime.strptime(in_date, '%Y-%m-%d')    # 从文件中读字符串并解析为日期
            return date
        except ValueError as e:
            print('处理ValueError异常')
            print(e)
    except FileNotFoundError as e:
        print('处理FileNotFoundError异常')
        print(e)
    except OSError as e:
        print('处理OSError异常')
        print(e)


date = read_date_from_file('readme.txt')
print('日期 = {0}'.format(date))

注意:try-except不仅可以嵌套在try代码块中,还可以嵌套在except代码块或finally代码块。嵌套会使程序流程变得复杂,尽量不用。

14.4.4 多重异常捕获 

有些异常虽然类型不同,但捕获后的处理是相同的。

try:

        <可能会抛出异常的语句>

except ValueError as e:

        <调用方法method处理>

except OSError as e:

        <调用方法method处理>

except FileNotFoundError as e:

        <调用方法method处理>

三个不同类型的异常,捕获之后的处理都是method方法。可以把这些异常放到一个元组,这就是多重异常捕获。

import datetime as dt


def read_date_from_file(filename):
    try:
        file = open(filename)
        in_date = file.read()
        in_date = in_date.strip()   # in_date.strip()提出字符串前后空白字符(包括空格、制表符、换行和回车等字符)
        date = dt.datetime.strptime(in_date, '%Y-%m-%d')    # 从文件中读字符串并解析为日期
        return date
    except (ValueError, OSError) as e:
        print('处理ValueError异常')
        print(e)

date = read_date_from_file('readme.txt')
print('日期 = {0}'.format(date))

14.5 异常堆栈跟踪

从程序员角度需要知道更加详细的异常信息,可以打印堆栈信息。可以通过Python内置模块traceback提供的print_exc()函数实现,print_exc()函数的语法格式:

traceback.print_exc(limit=None, file=None, chain=None)

limit限制堆栈跟踪个数,默认None不限制。

file判断是否输出堆栈跟踪信息到文件,默认None是不输出到文件。

chain为True,则将_cause_和_context_等属性串联起来,就像解释器本省打印未处理异常一样。

import datetime as dt
import traceback as tb

def read_date_from_file(filename):
    try:
        file = open(filename)
        in_date = file.read()
        in_date = in_date.strip()   # in_date.strip()提出字符串前后空白字符(包括空格、制表符、换行和回车等字符)
        date = dt.datetime.strptime(in_date, '%Y-%m-%d')    # 从文件中读字符串并解析为日期
        return date
    except (ValueError, OSError) as e:
        print('调用method处理...')
        tb.print_exc()

date = read_date_from_file('readme.txt')
print('日期 = {0}'.format(date))

14.6 释放资源 

 有时try-except语句会占用一些资源,如打开文件、网络连接、打开数据库连接和使用数据结果集等,这些资源不能通过Python的垃圾收集回收,需要程序员释放。为了确保这些资源能够被释放,可以使用finally代码块或自动资源管理。

14.6.1 finally代码块

 try-except语句后面可以跟一个finally代码块。try-except-finally语句语法如下:

try:

        <可能会抛出异常的语句>

except [异常类型1]:

        <处理异常>

except [异常类型2]:

        <处理异常>

...

except [异常类型n]:

        <处理异常>

finally :

        <释放资源>

无论try正常结束还是except异常结束都会执行finally代码块。

import datetime as dt

def read_date_from_file(filename):
    try:
        file = open(filename)
        in_date = file.read()
        in_date = in_data.strip()
        date = dt.datetime.strptime(in_date, '%Y-%m-%d')
        return date
    except ValueError as e:
        print('处理ValueError异常')
    except FileNotFoundError as e:
        print('处理FileNotFoundError异常')
    except OSError as e:
        print('处理OSError异常')
    finally:
        file.close()


date = read_date_from_file('readme.txt')
print('日期 = {0}'.format(date))

14.6.2 else代码

 else是在程序正常结束时执行的代码块。

 

import datetime as dt

def read_date_from_file(filename):
    try:
        file = open(filename)
    except OSError as e:
        print('打开文件失败')
    else:
        print('打开文件成功')
        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('处理ValueError异常')
        except OSError as e:
            print('处理OSError异常')
        finally:
            file.close()


date = read_date_from_file('readme.txt')
print('日期 = {0}'.format(date))

14.6.3 with as代码块自动资源管理 

14.6.2示例的程序比较复杂,程序代码难以维护。

with as 代码块帮助自动释放资源,可以替代finally代码块,优化代码结构。

with as 提供了一个代码块,在as后面声明一个资源变量,当with as代码块结束之后自动释放资源。

import datetime as dt

def read_date_from_file(filename):
    try:
        with open(filename) as file:
            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('处理ValueError异常')
    except OSError as e:
        print('处理OSError异常')

date = read_date_from_file('readme.txt')
print('日期 = {0}'.format(date))

with语句后面的open(fliename)语句可以创建资源对象,然后可以赋值给as后面的file变量。

注意:所有可以自动管理的资源,需要实现上下文管理协议(Content Management Protocol)

14.7 自定义异常类

 有些公司为了提高代码的可重用性,自己开发了一些Python类库,其中有自己编写的一些异常类。实现自定义异常类需要继承Exception类或其子类。

class MyException(Exception):
    def __init__(self, message):    # message时异常描述信息
        super().__init__(message)
        # 调用父类构造方法,把参数message传入父类构造方法

14.8 显式抛出异常

 本节之前的异常都是系统生成的,当异常抛出时,系统会创建一个异常对象,并将其抛出,也可以通过raise语句显式抛出异常,语法结构:

raise BaseException或其子类的实例

显式抛出的异常目的很多,例如不想某些异常传给上层调用者,可以捕获之后重新显式抛出另外一种异常给调用者。也就是异常自己处理。

import datetime as dt

class MyException(Exception):
    def __init__(self, message):    # message时异常描述信息
        super().__init__(message)
        # 调用父类构造方法,把参数message传入父类构造方法

def read_date_from_file(filename):
    try:
        file = open(filename)
        in_date = file.read()
        in_date = in_date.strip()
        date = dt.datetime.strptime(in_date, '%Y-%m-%d')
        return date
    except ValueError as e:
        raise MyException('不是有效日期')
    except FileNotFoundError as e:
        raise MyException('文件找不到')
    except OSError as e:
        raise MyException('文件无法打开或无法读取')

date = read_date_from_file('readme.txt')
print('日期 = {0}'.format(date))

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
《从实例学SAP ABAP编程1-10章》是一本SAP ABAP编程的经典入门教材。本书从简单的SAP ABAP编程入手,通过多个实例向读者展示了SAP ABAP编程的核心概念和语法。 在第一章中,本书通过一个简单的例子介绍了SAP ABAP编程的基础知识,讲解了ABAP编辑器、ABAP数据字典和ABAP Workbench等重要工具的用法。 在第二章中,本书通过一个简单的例子向读者介绍了ABAP表格的创建和维护,并讲解了一些与表格相关的SAP ABAP编程的语法和概念。 在第三章中,本书介绍了SAP ABAP编程中的面向对象编程,通过几个例子向读者展示了如何使用类、对象和继承等概念进行SAP ABAP编程。 在第四章中,本书介绍了SAP ABAP编程中的函数模块,向读者讲解了如何创建和调用函数模块,以及如何在SAP系统中使用函数模块。 在第五章中,本书介绍了SAP ABAP编程中的异常处理,向读者讲解了如何使用TRY/CATCH语句处理SAP系统中的异常情况。 在第六章中,本书介绍了SAP ABAP编程中的Web服务,向读者讲解了如何创建和使用SAP系统中的Web服务,以及如何使用HTTP和SOAP协议进行数据通信。 在第七章中,本书介绍了SAP ABAP编程中的ALV报表,向读者讲解了如何创建和维护SAP系统中的ALV报表,以及如何对报表进行数据操作和定制。 在第八章中,本书介绍了SAP ABAP编程中的BADI和Enhancement点,向读者讲解了如何使用BADI和Enhancement点扩展和修改SAP系统中的业务逻辑。 在第九章中,本书介绍了SAP ABAP编程中的Smart Form,向读者讲解了如何使用Smart Form创建和维护SAP系统中的表单。 在第十章中,本书介绍了SAP ABAP编程中的SAP HANA数据库,向读者讲解了如何使用SAP HANA数据库进行高效的数据处理和分析。 通过阅读本书,读者可以快速掌握SAP ABAP编程的核心知识和技能,从而能够独立进行SAP系统的开发和维护工作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值