with 上下文管理器

上下文管理器

with 的语法格式:

1
2
with context_expression [as target(s)]:
with-body

with 语法非常简单,我们只需要 with 一个表达式,然后就可以执行自定义的业务逻辑。

1
2
3
4
with open('file.txt') as f:
for line in f:
# do_something...

with 非常简单,我们只需要 with 一个表达式,然后就可以执行自定义的业务逻辑。

一个类在 Python 中,只要实现以下方法,就实现了 「 上下文管理协议 」:

  • __enter__: 在进入 with 语法块之前调用,返回值会赋值给 withtarget
  • __exit__: 在退出 with 语法块时调用,一般用作异常处理

contextlib 模块

使用 contextlib 模块,我们可以把上下文管理器当成一个 「 装饰器 」来使用。

1
2
3
4
5
6
7
8
9
10
11
12
from contextlib import contextmanager


@contextmanager
def test():
print("before")
yield 'hello'
print("after")


with test() as t:
print(t)

closing 方法

closing 主要用在已经实现close方法的资源对象上:

使用场景

Redis 分布式锁

1
2
3
4
5
6
7
8
9
10
11
12
13
@contextmanager
def lock(redis, lock_key, expire):
try:
locked = redis.set(lock_key, 'locked', expire)
yield locked
finally:
redis.delete(lock_key)

# 业务调用 with 代码块执行结束后 自动释放资源
with lock(redis, 'locked', 3) as locked:
if not locked:
return
# do something

redis 事务和管道

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from contextlib import contextmanager

@contextmanager
def pipeline(redis):
pipe = redis.pipeline()
try:
yield pipe
pipe.execute()
except Exception as exc:
pipe.reset()


# 业务调用 with 代码块执行结束后 自动执行 excute 方法
with pipeline(redis) as pipe:
pipe.set("key1", 'a', 30)
pipe.zadd('key2', 'a', 1)
pipe.sadd('key3', 'a')
-------------THANKS FOR READING-------------