使用普通multiprocessing.Lock
(或threading.Lock
(可以简化以下代码:
lock = multiprocessing.Lock()
lock.acquire()
try:
...
finally:
lock.release()
进入:
with lock:
...
但是,当我想将一些参数传递给lock.acquire(...)
(如block=
或timeout=
(时,我还能使用上下文管理器吗?例如,我有这样的代码:
lock_success = lock.acquire(block=False)
if not lock_success:
return
try:
...
finally:
lock.release()
我看不出有什么方法可以将此参数传递给上下文管理器(因为它在acquire
调用中,而不是构造函数中(。
(这个想法是,如果无法获取锁,with
-块将被跳过。(
类似于提供类似API的threading.Lock
。
TLDR;您不能使用内置的锁上下文管理器,但它仍然可以相当干净地完成。
它几乎可以工作,因为Lock.__enter__()
确实返回了从对acquire()
的调用返回的值,该值应该是获取锁的布尔成功或失败。
l = Lock()
with l as success:
if success:
print("run some code")
else:
print("skip the code")
然而,令人沮丧的是,无法将参数传递给acquire
的内部调用(此处为硬编码参数(。我建议您编写自己的上下文管理器来解决这个问题,因为它非常简单:
from multiprocessing import Lock
from contextlib import contextmanager
@contextmanager
def get_lock(lock, block=True, timeout=None):
held = lock.acquire(block=block, timeout=timeout)
try:
yield held
finally:
if held:
lock.release()
#### example usage ####
l = Lock()
#lock should be acquired so success == True
with get_lock(l) as success:
if success:
print("run some code")
else:
print("skip the code")
l.acquire()
#lock won't be acquired and block will proceed after timeout
#use the value of success to determine what to do
with get_lock(l, True, 3) as success:
if success:
print("run some code")
else:
print("skip the code")
l.release()
我怀疑这是不可能的,因为上下文管理器是如何在Python中设计的。上下文管理器(CM(的作用是:
with CM:
...
- CM的
__enter__
方法被调用 with
内部的块运行- CM的
__exit__
方法被调用
因此;跳过";with
块的内部,所以我想这解释了Lock
类的设计。尽管有一些黑暗的魔法方法(应该避免(。