Loading

Python--异常与错误处理、上下文管理器

一些常用的知识

一:优先使用异常捕获
二:把更精确的except语句放在前面,异常类的派生关系一般是BaseException -> Exception -> LookupError -> KeyError
三:使用空raise语句,当做相关操作之后原封不动地继续抛出当前异常

def safe_int(value):
    try:
        return int(value)
    except TypeError as e:
        raise
    except ValueError as e:
        raise
    finally:
        print('Function safe_int completed')


if __name__ == '__main__':
    res1 = safe_int(None)
    res2 = safe_int('abc')
    print(res1)
    print(res2)

else分支

异常捕获语句里的else表示:仅当try语句块里没有抛出任何异常时,才执行else分支的内容
它跟finally语句不同,假如程序在执行try代码块时碰到了return或break等跳转语句时,中断本次异常捕获,那么即便代码没有抛出任何异常,else分支语句也不会被执行,而finally则是始终会执行

上下文管理器

一个简单地例子

class MyContext:
    def __init__(self, name):
        self.name = name

    def __enter__(self):
		# __enter__的返回值被as后面的变量接收
        self.name = f'Big {self.name}'
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
		# __exit__在with中的语句结束之后立即执行
		# 假如with管辖的上下文内没有抛出任何异常,当解释器出发__exit__方法时,其三个参数都为None,如果有异常抛出则三个参数会有具体内容
		# exc_type:异常类型,exc_value:异常对象,traceback:错误的堆栈对象
		# __exit__返回值:True:异常被忽略, False:异常正常抛出
        print('Exiting MyContext')
        return False


if __name__ == '__main__':
    with MyContext('王大锤') as me:
        print(me.name)

使用contextmanager装饰器

把一个生成器函数快速转换为一个上下文管理器

from contextlib import contextmanager


class Conn:
    def __init__(self, host, port):
        self.host = host
        self.port = port

    def close(self):
        print('conn closed')
        pass


@contextmanager
def get_conn_obj(host, port):
    """
    1. yield之前的逻辑会在进入管理器时执行(类似__enter__),yield之后会在退出管理器时执行(类似__exit__)
    2. 如果在上下文管理器内处理异常,则需要使用try语句包裹yield语句
    """
    conn = Conn(host, port)
    try:
        yield conn
    finally:
        conn.close()


if __name__ == '__main__':
    with get_conn_obj('localhost', 3306) as conn:
        print(conn.host, conn.port)
posted @ 2022-04-24 21:01  MrSu  阅读(197)  评论(0编辑  收藏  举报