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

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

with ContextIllustration():
    raise RuntimeError("raised within 'with'")

运行结果如下

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

你可能感兴趣的:(python高级用法,python,开发语言)