'Acquire a multiprocessing.Lock in a with statement if non-blocking or with timeout

With a normal multiprocessing.Lock (or threading.Lock) you can simplify the following code:

lock = multiprocessing.Lock()
lock.acquire()

try:
    ...
finally:
    lock.release()

into:

with lock:
    ...

However, can I still use a context manager when I want to pass some arguments to lock.acquire(...), such as block= or timeout=? For example, I have code like this:

lock_success = lock.acquire(block=False)

if not lock_success:
    return

try:
    ...
finally:
    lock.release()

I don't see a way to pass this argument to the context manager (since it's in the acquire call and not the constructor).

(The idea is that the with-block would get skipped if the lock cannot be acquired.)

Analogously for threading.Lock which provides a similar API.



Solution 1:[1]

My suspicion is that this is not possible because of how context managers are designed in Python. What happens with a context manager (CM) is:

with CM:
    ...
  • The CM's __enter__ method is called
  • The block inside of with is run
  • The CM's __exit__ method is called

Thus there is no way to "skip" the inside of the with-block, so I guess this explains the design of the Lock class. Although there are some dark magic ways around that (which should be avoided).

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 xjcl