笔记-python-lib-contextlib

笔记-python-lib-contextlib

 

1.      contextlib

with 语句很好用,但不想每次都写__enter_-和__exit__方法;

 

py标准库也为此提供了工具模块contextlib

模块提供的功能有很多,重点说一下contextmanager

 

2.      contextmanager

它提供了一个简单的上下文环境

简单使用:

from contextlib import contextmanager

 

@contextmanager

def make_open_context(filename, mode):

    fp = open(filename, mode)

    try:

        yield fp

    finally:

        fp.close()

 

with make_open_context('i002.txt','a') as fi:

    fi.write('hello ')

 

不用创建类和写__enter__,__exit__方法。

 

2.1.    代码释义

def contextmanager(func):

    """@contextmanager decorator.

 

    Typical usage:

 

        @contextmanager

        def some_generator(<arguments>):

            <setup>

            try:

                yield <value>

            finally:

                <cleanup>

 

    This makes this:

 

        with some_generator(<arguments>) as <variable>:

            <body>

 

    equivalent to this:

 

        <setup>

        try:

            <variable> = <value>

            <body>

        finally:

            <cleanup>

 

    """

    @wraps(func)

    def helper(*args, **kwds):

        return _GeneratorContextManager(func, args, kwds)

    return helper

contextmanager是一个装饰器函数,去掉注释,实际上是返回一个中间函数helper,helper返回的则是一个上下文管理器,具体的实现可以看下代码。

 

2.2.    _GeneratorContextManager(func, args, kwds)

前序准备工作非常简单,主要是后续清理代码比较多。

 

    def __enter__(self):

        try:

            return next(self.gen)

        except StopIteration:

            raise RuntimeError("generator didn't yield") from None

 

    def __exit__(self, type, value, traceback):

        if type is None:

            try:

                next(self.gen)

            except StopIteration:

                return False

            else:

                raise RuntimeError("generator didn't stop")

        else:

            if value is None:

                # Need to force instantiation so we can reliably

                # tell if we get the same exception back

                value = type()

            try:

                self.gen.throw(type, value, traceback)

            except StopIteration as exc:

                # Suppress StopIteration *unless* it's the same exception that

                # was passed to throw().  This prevents a StopIteration

                # raised inside the "with" statement from being suppressed.

                return exc is not value

            except RuntimeError as exc:

                # Don't re-raise the passed in exception. (issue27122)

                if exc is value:

                    return False

                # Likewise, avoid suppressing if a StopIteration exception

                # was passed to throw() and later wrapped into a RuntimeError

                # (see PEP 479).

                if type is StopIteration and exc.__cause__ is value:

                    return False

                raise

            except:

                # only re-raise if it's *not* the exception that was

                # passed to throw(), because __exit__() must not raise

                # an exception unless __exit__() itself failed.  But throw()

                # has to raise the exception to signal propagation, so this

                # fixes the impedance mismatch between the throw() protocol

                # and the __exit__() protocol.

                #

                if sys.exc_info()[1] is value:

                    return False

                raise

            raise RuntimeError("generator didn't stop after throw()")

 

 

3.      参考文档

参考文档:https://docs.python.org/3/library/contextlib.html?highlight=contextlib#module-contextlib

 

转载于:https://www.cnblogs.com/wodeboke-y/p/10489194.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值