-
-
Notifications
You must be signed in to change notification settings - Fork 33.1k
Description
Documentation
When using the contextmanager
decorator from contextlib
, the documentation clearly states how it should be used. However, it does not mention that a RuntimeError
is thrown when the provided generator never yields a value. See the following example:
@contextmanager
def my_optional_resource():
if resource_is_required():
resource = None
try:
resource = initialize_resource()
yield resource
finally:
if resource:
cleanup_resource(resource)
If in the example above is_resource_required()
is False
, the resource is never initialized and the generator never yields. Personally I expected nothing would actually happen and that the variable originating from the context manager would be None
in any with
statement using it. However it appears that (at least cpython) throws a RuntimeError
indicating that the generator did not yield.
It feels like it makes sense to throw an exception here, but it would be benificial to include this in the documentation.
For completeness, this is a full example to replicate the exception being thrown:
from contextlib import contextmanager
def resource_is_required():
return False
@contextmanager
def my_optional_resource():
if resource_is_required():
resource = None
try:
resource = initialize_resource()
yield resource
finally:
if resource:
cleanup_resource(resource)
with my_optional_resource() as resource:
print(resource)
This yields the following exception output:
Traceback (most recent call last):
File "main.py", line 17, in <module>
with my_optional_resource() as resource:
File "/usr/lib/python3.8/contextlib.py", line 115, in __enter__
raise RuntimeError("generator didn't yield") from None
RuntimeError: generator didn't yield
It appears that the same happens for the asynccontextmanager
decorator, but I did not attempt to replicate this.
Metadata
Metadata
Assignees
Labels
Projects
Status