搜索

查看: 3075|回复: 11

[Python] python中with的具体用法

[复制链接]
发表于 2023-5-4 17:20:37 | 显示全部楼层 |阅读模式
Editor 2023-5-4 17:20:37 3075 11 看全部
目录
  • 简介
  • 深入
  • 代码
    简介
    with的基本表达式如下
    with context_expression [as target(s)]:
        ...
        with-body
    其中context_expression 可以是任意的表达式,as target(s)是可选的
    他的执行过程如下
    context_manager = context_expression
    exit = type(context_manager).__exit__
    value = type(context_manager).__enter__(context_manager)
    exc = True   # True 表示正常执行,即便有异常也忽略;False 表示重新抛出异常,需要对异常进行处理
    try:
        try:
            target = value  # 如果使用了 as 子句
            with-body     # 执行 with-body
        except:
            # 执行过程中有异常发生
            exc = False
            # 如果 __exit__ 返回 True,则异常被忽略;如果返回 False,则重新抛出异常
            # 由外层代码对异常进行处理
            if not exit(context_manager, *sys.exc_info()):
                raise
    finally:
        # 正常退出,或者通过 statement-body 中的 break/continue/return 语句退出
        # 或者忽略异常退出
        if exc:
            exit(context_manager, None, None, None)
        # 缺省返回 None,None 在布尔上下文中看做是 False

    深入
    首先我们来了解两个概念,上下文管理对象与上下文协议
  • 上下文管理器:支持上下文管理协议的对象,这里我们就要知道什么是上下文管理管理协议了,请看第二点。上下文管理器运行with语句是要建立运行的上下文,负责执行with语句块上下文中的进入与退出操作。
  • 上下文管理协议:包含方法__enter__()和__exit__(),支持协议的对象要实现这两个方法
    理解完上面的两点,我们就很容易知道with语句的执行流程,我们看着上面的执行过程代码来看
  • 执行context_expression ,生成山下文管理器context_manager
  • 调用上下文管理器的__enter__方法,这个时候如果使用了as,那么就会将__enter__方法的返回值赋值给target
  • 执行with-body
  • 不管执行过程中是否发生了异常都会执行上下文管理器的__exit__方法,它用于负责执行清理工作,如释放资源等。
  • 如果执行过程中没有出现异常,或者语句中执行了语句break/continue/return,则以None作为参数调用__exit__(None,None,None);如果执行过程中出现了异常,则使用sys.excinfo得到异常信息作为参数调用__exit__(exc_type,exc_value,exc_traceback)
  • 出现异常时,如果__exit__(exc_type,exc_value,exc_traceback)返回false,则会重新抛出异常,让with完的语句来处理异常,如果__exit__(exc_type,exc_value,exc_traceback)返回True,则异常忽略,不在对于异常来进行处理
    代码
    没有报错
    class Test:
        def __enter__(self):
            print("__enter__")
            return "hello python"
        def __exit__(self, type, value, trace):
            print("__exit__")
            pass
    def get_test():
        return Test()
    with get_test() as test:
        print(test)
    他的打印如下
    __enter__
    hello python
    __exit__

    有报错
    class Test:
        def __enter__(self):
            print("__enter__")
            return "hello python"
        def __exit__(self, type, value, trace):
            print("type", type)
            print("value", value)
            print("trace", trace)
            print("__exit__")
    def get_test():
        return Test()
    with get_test() as test:
        print(test)
        1 / 0
    打印如下
    hello python
    type
    value division by zero
    trace [tr]
    __exit__
    Traceback (most recent call last):
      File "f:/my_profile/study/code_pub/study_code_pub/python/关键字/with.py", line 35, in
        1 / 0

    可以看出来当有报错的时候,他是抛出了异常,因为__exit__没有返回值,当他返回True的时候,他的打印如下
    当__exit__返回True时
    __enter__
    hello python
    type
    value division by zero
    trace [tr]
    __exit__

    我们会发现他没有了报错信息
    到此这篇关于python中with的具体用法的文章就介绍到这了,更多相关python with使用内容请搜索知鸟论坛以前的文章或继续浏览下面的相关文章希望大家以后多多支持知鸟论坛
  • 回复

    使用道具 举报

    发表于 2023-6-28 19:14:19 | 显示全部楼层
    幸福341 2023-6-28 19:14:19 看全部
    论坛不能没有像楼主这样的人才啊!我会一直支持知鸟论坛
    回复

    使用道具 举报

    发表于 2023-6-28 22:21:23 | 显示全部楼层
    当当当当裤裆坦 2023-6-28 22:21:23 看全部
    这东西我收了!谢谢楼主!知鸟论坛真好!
    回复

    使用道具 举报

    发表于 2023-6-28 22:55:29 | 显示全部楼层
    123456825 2023-6-28 22:55:29 看全部
    既然你诚信诚意的推荐了,那我就勉为其难的看看吧!知鸟论坛不走平凡路。
    回复

    使用道具 举报

    发表于 2023-6-29 23:48:42 | 显示全部楼层
    462710480 2023-6-29 23:48:42 看全部
    论坛不能没有像楼主这样的人才啊!我会一直支持知鸟论坛
    回复

    使用道具 举报

    发表于 2023-6-30 01:02:35 | 显示全部楼层
    音乐之家1 2023-6-30 01:02:35 看全部
    既然你诚信诚意的推荐了,那我就勉为其难的看看吧!知鸟论坛不走平凡路。
    回复

    使用道具 举报

    发表于 2023-6-30 01:06:31 | 显示全部楼层
    伊索谗言 2023-6-30 01:06:31 看全部
    论坛不能没有像楼主这样的人才啊!我会一直支持知鸟论坛
    回复

    使用道具 举报

    发表于 2023-6-30 09:57:32 | 显示全部楼层
    无人岛屿颈 2023-6-30 09:57:32 看全部
    这个帖子不回对不起自己!我想我是一天也不能离开知鸟论坛
    回复

    使用道具 举报

    发表于 2023-6-30 13:45:10 | 显示全部楼层
    塞翁364 2023-6-30 13:45:10 看全部
    这个帖子不回对不起自己!我想我是一天也不能离开知鸟论坛
    回复

    使用道具 举报

    发表于 2023-6-30 15:57:30 | 显示全部楼层
    计划你大爷计j 2023-6-30 15:57:30 看全部
    楼主太厉害了!楼主,I*老*虎*U!我觉得知鸟论坛真是个好地方!
    回复

    使用道具 举报

    • 您可能感兴趣
    点击右侧快捷回复 【请勿灌水】
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则 返回列表

    RSS订阅| SiteMap| 小黑屋| 知鸟论坛
    联系邮箱E-mail:zniao@foxmail.com
    快速回复 返回顶部 返回列表