Python笔记----异常处理

Python笔记----异常处理

异常处理
Python的异常机制主要依赖:try,except,else,finally,raise五个关键字。

  • try块放置的是可能引发异常的代码;
  • except后对应的是异常类型和一个代码块,用于表明该except块处理这种类型的代码;
  • 在多个except块之后可以放一个else块,表明程序不出现异常时还要执行else块;
  • finally块用于回收在try块中打开的物理资源,异常机制保障finally块总被执行;
  • raise用于引发一个实际的异常。raise可单独作为语句使用,引发一个具体的异常对象。

异常概述
使用异常处理机制的Python程序有更好的容错性,更加健壮。

异常处理机制

1.使用try…except捕获异常
以下是Python异常处理机制的语法结构:

www.zeeklog.com  - Python笔记----异常处理

​ 如果在执行 try 块里的业务逻辑代码时出现异常,系统自动生成一个异常对象,该异常对象被提交给Python 解释器,这个过程被称为引发异常。
​ 当Python解释器收到异常对象时,会寻找能处理该异常对象的 except 块,如果找到合适的except 块,则把该异常对象交给该 except 块处理,这个过程被称为捕获异常。
​ 如果 Python 解释器找不到捕获异常的 except 块,则运行时环境终止, Python 解释器也将退出。
​ 不管程序代码块是否处于try块中,甚至包括 except 块中的代码,只要执行该代码块时出现了异常,系统总会自动生成一个 Error 对象。例如:

www.zeeklog.com  - Python笔记----异常处理

2.异常类的继承体系
当程序发生不同的意外情况时,系统会生成不同的异常对象, Python 解释器就 会根据该异常对象所属的异常类来决定使用哪个 except块处理该异常。
Python的所有异常类都从 BaseException 生而来,提供 丰富的异常类。

www.zeeklog.com  - Python笔记----异常处理

​ Python 的所有异常类的基类是 BaseException ,但如果用户要实现自定义异常,则不应该继承这个基类,而是应该继承 Exception 类。

import sys

try:
    a = int(input())
    b = int(input())
    c= a / b
    print('输入的两个数相除的结果为: ', c)
except IndexError:
    print('索引错误,运行程序时输入的参数个数不够')
except ValueError:
    print('数值错误,程序只能接收整数参数')
except ArithmeticError:
    print('算术错误,比如分母不应为0')
except Exception:
    print('未知异常')

运行结果如下:

www.zeeklog.com  - Python笔记----异常处理

3.多异常捕获
Python 的一个except 块可以捕获多种类型的异常。
将多个异常类用圆括号括起来,中间用逗号隔开,其实就是构建多个异常类的元组。

import sys

try:
    a = int(input())
    b = int(input())
    c= a / b
    print('输入的两个数相除的结果为: ', c)
except (IndexError, ValueError, ArithmeticError):
    print('索引错误,数值错误,算术错误之一')
except:
    print('未知异常')

​ 最后一行代码只有 except 关键字,并未指定具体要捕获的异常类型,这种省略异常类的 except 语句也是合法的,它表示可捕获所有类型的异常,一般会作为异常捕获的最后一个except块。

4.访问异常信息
如果程序需要在 except 块中访问异常对象的相关信息,则可通过为异常对象声明变量来实现。当Python 解释器决定调用某个 except 块来处理该异常对象时,会将异常对象赋值给 except 块后的 异常变量,程序即可通过该变量来获得异常对象的相关信息。
所有的异常对象都包含了如下几个常用属性和方法:

  • args :该属性返回异常的错误编号和描述字符串。
  • errno :该属性返回异常的错误编号。
  • stre or :该属性返回异常的描述宇符串。
  • with_traceback(): 通过该方法可处理异常的传播轨迹信息。
'''
演示如何访问异常信息
'''

def foo():
    try:
        fis = open('aaa.txt')
    except Exception as e:
        #访问异常的错误编号和详细信息
        print(e.args)
        #访问异常的错误编号
        print(e.errno)
        #访问异常的详细信息
        print(e.strerror)
        
foo()

运行结果如下:

www.zeeklog.com  - Python笔记----异常处理

​ 如果要访问异常对象,只要在单个异常类或异常类元组(多异常捕获) 之后使用 as 再加上异常变量即可。

5.else块
Python 的异常处理流程中还可添加else块,当 try 块没有出现异常时,程序会执行else块。

s = input('请输入除数')
try:
    result = 20 / int(s)
    print('20除以%s的结果是: %g' % (s, result))
except ValueError:
    print('值错误, 你必须输入数值')
except ArithmeticError:
    print('0不可以做除数')
else:
    print('无异常')

运行结果如下:

www.zeeklog.com  - Python笔记----异常处理

​ 当 try 块没有异常,而else块有异常时,就能体现出else 块的作用了。

def else_test():
    s = input('请输入除数')
    result = 20 / int(s)
    print('20除以%s的结果是: %g' % (s, result))


def right_main():
    try:
        print('try块无异常')
    except:
        print('程序出现异常')
    else:
        # 将else_test放在else中
        else_test()


def wrong_main():
    try:
        print('try块的代码无异常')
        # 将else_test放在try的代码的后面
        else_test()
    except:
        print('程序出现异常')


wrong_main()
right_main()

运行结果如下:

www.zeeklog.com  - Python笔记----异常处理

​ 对比上面两个输出结果,不难发现,放在 else 块中的代码所引发的异常不会被except 块捕获。 如果希望某段代码的异常能被后面 except 块捕获,那么就应该将这段代码放在 try 块的代码之后。 如果希望某段代码的异常能向外传播(不被 except 块捕获〉,那么就应该将这段代码放在 else 块中。该异常将会传播给 python 解释器, 导致程序中止 。

6.使用finally回收资源
有些时候,程序在 try块里打开了一些物理资源(例如数据库连接、网络连接和磁盘文件等〉, 这些物理资源都必须被显式回收。
Python的垃圾回收机制不会回收任何物理资源,只能回收堆内存中对象所占用的内存。
Python完整的异常处理语法结构如下:

www.zeeklog.com  - Python笔记----异常处理
import os


def test():
    fis = None
    try:
        fis = open('a.txt')
    except OSError as e:
        print(e.strerror)
        
        # return语句强制方法返回
        # 执行到该语句,程序立即结束该方法
        # 但会执行finally块中的代码
        return 
    
		# 若将return注释,执行os.exit()方法,则不会执行finally块中的内容
		# os.exit()
    finally:
        # 关闭磁盘文件,回收资源
        if fis is not None:
            try:
                # 关闭资源
                fis.close()
            except OSError as ioe:
                print(ioe.strerror)
        print('执行finally块里的资源回收')
        
     
test()

​ 不要在 finally 块中使用如 return,raise等导致方法中止的语句,一旦在 finally 块中使用了 return或raise 语句,将会导致 try 块、 except 块中的 return或raise 语句失效。
​ 这是因为,如果 Python 程序在执行try块、 except 块时遇到了 return或raise 语句,这两条语句都会导致该方法立即结束,那么系统执行这两条语句并不会结束该方法,而是去找该异常处理流程中的 finally 块,如果没有找到 finally 块,程序立即执行 return或rais巳语句,方法中止;如果找到 finally 块,系统立即开始执行 finally 。只有当 finally 块执行完成后,系统才会再次跳回来执行 try 块、 except 块里的 return或raise语句:如果在finallt块里也使用了 return或raise 等导致方法中止的语句, finally 块己经中止了方法,系统将不会跳回去执行try块、 except 块里的任何代码。

7.异常处理的嵌套
在 finally 块中也包含了一个完整的异常处理流程,这种在 try 块、 except 块或 finally 块中包含完整的异常处理流程的情形被称为异常处理嵌套。
通常没有必要使用超过两层的嵌套异常处理,使用层次太深的嵌套异常处理没有太大必要,而且容易导致程序的可读性降低。

Read more

深入理解 Proxy 和 Object.defineProperty

在JavaScript中,对象是一种核心的数据结构,而对对象的操作也是开发中经常遇到的任务。在这个过程中,我们经常会使用到两个重要的特性:Proxy和Object.defineProperty。这两者都允许我们在对象上进行拦截和自定义操作,但它们在实现方式、应用场景和灵活性等方面存在一些显著的区别。本文将深入比较Proxy和Object.defineProperty,包括它们的基本概念、使用示例以及适用场景,以帮助读者更好地理解和运用这两个特性。 1. Object.defineProperty 1.1 基本概念 Object.defineProperty 是 ECMAScript 5 引入的一个方法,用于直接在对象上定义新属性或修改已有属性。它的基本语法如下: javascript 代码解读复制代码Object.defineProperty(obj, prop, descriptor); 其中,obj是目标对象,prop是要定义或修改的属性名,descriptor是一个描述符对象,用于定义属性的特性。 1.2 使用示例 javascript 代码解读复制代码//

By Ne0inhk

Proxy 和 Object.defineProperty 的区别

Proxy 和 Object.defineProperty 是 JavaScript 中两个不同的特性,它们的作用也不完全相同。 Object.defineProperty 允许你在一个对象上定义一个新属性或者修改一个已有属性。通过这个方法你可以精确地定义属性的特征,比如它是否可写、可枚举、可配置等。该方法的使用场景通常是需要在一个对象上创建一个属性,然后控制这个属性的行为。 Proxy 也可以用来代理一个对象,但是相比于 Object.defineProperty,它提供了更加强大的功能。使用 Proxy 可以截获并重定义对象的基本操作,比如访问属性、赋值、函数调用等等。在这些操作被执行之前,可以通过拦截器函数对这些操作进行拦截和修改。因此,通过 Proxy,你可以完全重写一个对象的默认行为。该方法的使用场景通常是需要对一个对象的行为进行定制化,或者需要在对象上添加额外的功能。 对比 以下是 Proxy 和 Object.defineProperty 的一些区别对比: 方面ProxyObject.defineProperty语法使用 new Proxy(target,

By Ne0inhk