如果非阻塞或超时,则在 with 语句中获取 multiprocessing.Lock
Acquire a multiprocessing.Lock in a with statement if non-blocking or with timeout
使用普通的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
块将被跳过。)
类似于 threading.Lock
,它提供了类似的 API。
我怀疑这是不可能的,因为 Python 中上下文管理器的设计方式。上下文管理器 (CM) 会发生什么:
with CM:
...
- 调用了CM的
__enter__
方法
with
里面的块是运行
- 调用了CM的
__exit__
方法
因此无法“跳过”with
-块的内部,所以我想这解释了 Lock
class 的设计。虽然围绕着它有一些 dark magic ways(应该避免)。
TLDR;你不能使用 built-in 锁上下文管理器,但它仍然可以相当干净地完成。
它几乎可以工作,因为 Lock.__enter__()
执行 return 从调用 acquire()
得到的值 return,这应该是获取锁的布尔值成功或失败.
l = Lock()
with l as success:
if success:
print("run some code")
else:
print("skip the code")
然而,令人沮丧的是,无法将参数传递给对 acquire
的内部调用(硬编码参数 here)。我建议您编写自己的上下文管理器来解决这个问题,因为它非常简单:
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()
使用普通的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
块将被跳过。)
类似于 threading.Lock
,它提供了类似的 API。
我怀疑这是不可能的,因为 Python 中上下文管理器的设计方式。上下文管理器 (CM) 会发生什么:
with CM:
...
- 调用了CM的
__enter__
方法 with
里面的块是运行- 调用了CM的
__exit__
方法
因此无法“跳过”with
-块的内部,所以我想这解释了 Lock
class 的设计。虽然围绕着它有一些 dark magic ways(应该避免)。
TLDR;你不能使用 built-in 锁上下文管理器,但它仍然可以相当干净地完成。
它几乎可以工作,因为 Lock.__enter__()
执行 return 从调用 acquire()
得到的值 return,这应该是获取锁的布尔值成功或失败.
l = Lock()
with l as success:
if success:
print("run some code")
else:
print("skip the code")
然而,令人沮丧的是,无法将参数传递给对 acquire
的内部调用(硬编码参数 here)。我建议您编写自己的上下文管理器来解决这个问题,因为它非常简单:
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()