diff --git a/Lib/contextlib.py b/Lib/contextlib.py index efc02bfa9243da..ba648416f84849 100644 --- a/Lib/contextlib.py +++ b/Lib/contextlib.py @@ -199,22 +199,18 @@ def __enter__(self): # do not keep args and kwds alive unnecessarily # they are only needed for recreation, which is not possible anymore del self.args, self.kwds, self.func - try: - return next(self.gen) - except StopIteration: - raise RuntimeError("generator didn't yield") from None + for value in self.gen: + return value + raise RuntimeError("generator didn't yield") def __exit__(self, typ, value, traceback): if typ is None: - try: - next(self.gen) - except StopIteration: - return False - else: + for _ in self.gen: try: raise RuntimeError("generator didn't stop") finally: self.gen.close() + return False else: if value is None: # Need to force instantiation so we can reliably @@ -272,22 +268,18 @@ async def __aenter__(self): # do not keep args and kwds alive unnecessarily # they are only needed for recreation, which is not possible anymore del self.args, self.kwds, self.func - try: - return await anext(self.gen) - except StopAsyncIteration: - raise RuntimeError("generator didn't yield") from None + async for value in self.gen: + return value + raise RuntimeError("generator didn't yield") async def __aexit__(self, typ, value, traceback): if typ is None: - try: - await anext(self.gen) - except StopAsyncIteration: - return False - else: + async for _ in self.gen: try: raise RuntimeError("generator didn't stop") finally: await self.gen.aclose() + return False else: if value is None: # Need to force instantiation so we can reliably diff --git a/Misc/NEWS.d/next/Library/2026-07-01-16-39-54.gh-issue-151903.1Jm-Oc.rst b/Misc/NEWS.d/next/Library/2026-07-01-16-39-54.gh-issue-151903.1Jm-Oc.rst new file mode 100644 index 00000000000000..3a09e4eb653f28 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-07-01-16-39-54.gh-issue-151903.1Jm-Oc.rst @@ -0,0 +1 @@ +Optimize ``contextlib.contextmanager`` and ``contextlib.asynccontextmanager`` by replacing explicit ``next()`` and ``anext()`` calls with ``for`` and ``async for`` loops.