如何重用自定义@contextlib.contextmanager?
How to reuse a custom @contextlib.contextmanager?
我正在尝试创建一个包装器以使上下文对象成为可选的。当条件为真时,事物应该表现得像包装的上下文对象,否则它应该表现得像无操作上下文对象。此示例适用于一次使用包装对象,但失败了它被重新使用。
示例:
import contextlib
from threading import Lock
@contextlib.contextmanager
def conditional_context(context, condition):
if condition and context:
with context:
yield
else:
yield
use_locking = False
lock = conditional_context(Lock(), use_locking)
with lock:
print('Foo')
with lock:
print('Bar')
输出:
Foo
Traceback (most recent call last):
File "example.py", line 16, in <module>
with lock:
File "/usr/lib/python3.5/contextlib.py", line 61, in __enter__
raise RuntimeError("generator didn't yield") from None
RuntimeError: generator didn't yield
你不能用 contextlib.contextmanager
做到这一点。正如在 the docs 中传递的那样,由 contextmanager 创建的上下文管理器是一次性的。
如果您希望同一个对象可在多个 with
语句中重复使用,您将必须使用 __enter__
和 __exit__
方法编写自己的 class:
from threading import Lock
class ConditionalContext:
def __init__(self, context, condition):
self._context = context
self._condition = condition
def __enter__(self, *args, **kwargs):
if self._condition:
self._context.__enter__(*args, **kwargs)
def __exit__(self, *args, **kwargs):
if self._condition:
self._context.__exit__(*args, **kwargs)
use_locking = False
lock = ConditionalContext(Lock(), use_locking)
with lock:
print('Foo')
with lock:
print('Bar')
我正在尝试创建一个包装器以使上下文对象成为可选的。当条件为真时,事物应该表现得像包装的上下文对象,否则它应该表现得像无操作上下文对象。此示例适用于一次使用包装对象,但失败了它被重新使用。
示例:
import contextlib
from threading import Lock
@contextlib.contextmanager
def conditional_context(context, condition):
if condition and context:
with context:
yield
else:
yield
use_locking = False
lock = conditional_context(Lock(), use_locking)
with lock:
print('Foo')
with lock:
print('Bar')
输出:
Foo
Traceback (most recent call last):
File "example.py", line 16, in <module>
with lock:
File "/usr/lib/python3.5/contextlib.py", line 61, in __enter__
raise RuntimeError("generator didn't yield") from None
RuntimeError: generator didn't yield
你不能用 contextlib.contextmanager
做到这一点。正如在 the docs 中传递的那样,由 contextmanager 创建的上下文管理器是一次性的。
如果您希望同一个对象可在多个 with
语句中重复使用,您将必须使用 __enter__
和 __exit__
方法编写自己的 class:
from threading import Lock
class ConditionalContext:
def __init__(self, context, condition):
self._context = context
self._condition = condition
def __enter__(self, *args, **kwargs):
if self._condition:
self._context.__enter__(*args, **kwargs)
def __exit__(self, *args, **kwargs):
if self._condition:
self._context.__exit__(*args, **kwargs)
use_locking = False
lock = ConditionalContext(Lock(), use_locking)
with lock:
print('Foo')
with lock:
print('Bar')