Python高级用法:上下文

上下文

上下文的实现一般可以通过装饰器或者上下文管理器实现,装饰器确保函数可以运行在正确的上下文中,或者在函数前后运行一些代码。

上下文装饰器

当一个数据项需要在多个线程之间共享时,就要用一个锁来保护它避免多次访问。这个锁可以在装饰器中编写(当然也可以不使用修饰器),代码如下:

from threading import RLock
lock = RLock()

def synchronized(function):
    def _synchronized(*args, **kw):
        lock.acquire()
        try:
            return function(*args, **kw)
        finally:
            lock.release()
    return _synchronized

@synchronized
def thread_safe(): # 确保锁定资源
    pass

关于修饰器的构建本系列的文章已经介绍过了,不再赘述,在代码中创建了一个互斥锁,这里是将函数调用作为临界区,防止被多次调用。关于互斥锁的使用暂时不必深究,只需要知道他是一种线程共享的方式即可。

上下文管理器

为了确保即使在出现错误的情况下也能运行某些清理代码,try…finally语句是很有用的。如关闭文件、释放锁、创建临时代码补丁等功能。

with语句为这些使用场景下的代码块包装提供了一种简单方法。即使该代码块引发了异常,也可以在其执行前后调用一些代码。

with语句

我们熟悉的文件打开方式就是如此,假设我们有一个名为:test.txt的文件,打开过程可以是以下方式打开:

with open("test.txt") as f:
	# 可以在这里进行对文件的操作
	pass

上面打开方式的优点就是不需要调用close对文件进行关闭,保证了文件随用随关。

创建一个上下文管理器

任何实现了上下文管理器协议(context manager protocol)的对象都可以用作上下文管理器。该协议包含两个特殊方法。

  • __ enter __ (self):
  • __ exit __ (self, exc _ type, exc _ value, traceback):

简而言之,执行with语句的过程如下:

  1. 调用__ enter __方法。任何返回值都会绑定到指定的as子句。
  2. 执行内部代码块。
  3. 调用__ exit __方法。

__ exit __接受代码块中出现错误时填入的3个参数。如果没有出现错误,那么这3个参数都被设为None。

出现错误时,__ exit__不会重新引发这个错误,但它可以通过返回True来避免引发异常。

下面是某个实现了这一协议的上下文管理器示例

class ContextIllustration:
     def __enter__(self):
        print('entering context')

     def __exit__(self, exc_type, exc_value, traceback):
        print('leaving context')
        if exc_type is None:
            print('with no error')
        else:
            print('with an error (%s)' % exc_value)

在这里enter就是来凑数的,我们主要来看exit的部分

当遇到报错时三个参数不为None,所以只需要判断其中一个参数就可以得知是否有报错了。其中exc_type是异常值类型, exc_value是异常值。

正常调用未引起报错的情况如下:

with ContextIllustration():
    print("inside")

运行结果:

entering context
inside
leaving context
with no error

为了营造错误使用的情况,我们这里直接抛出错误

entering context
leaving context
with an error (raised within 'with')

相关推荐

  1. Python高级用法上下文

    2024-01-08 09:22:02       36 阅读
  2. Python高级用法:property

    2024-01-08 09:22:02       30 阅读
  3. Python高级用法:装饰器用于缓存

    2024-01-08 09:22:02       41 阅读
  4. Python高级用法:描述符(descriptor)

    2024-01-08 09:22:02       32 阅读
  5. Python高级用法:装饰器用于参数检查

    2024-01-08 09:22:02       31 阅读
  6. Python】Flask上下文管理

    2024-01-08 09:22:02       19 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-01-08 09:22:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-08 09:22:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-08 09:22:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-08 09:22:02       20 阅读

热门阅读

  1. 找不到模块 “path“ 或其相对应的类型声明

    2024-01-08 09:22:02       39 阅读
  2. Spring之单元测试

    2024-01-08 09:22:02       31 阅读
  3. 【csharp】依赖注入

    2024-01-08 09:22:02       33 阅读
  4. Mockito+junit5搞定单元测试

    2024-01-08 09:22:02       37 阅读
  5. 无人驾驶游艇

    2024-01-08 09:22:02       35 阅读
  6. 鸡尾酒效应通俗解释,举一个具体的例子。

    2024-01-08 09:22:02       39 阅读
  7. 【设计模式】观察者模式

    2024-01-08 09:22:02       33 阅读
  8. 力扣_day1

    2024-01-08 09:22:02       40 阅读