gh-93453: No longer create an event loop in get_event_loop() (#98440)

asyncio.get_event_loop() now always return either running event loop or
the result of get_event_loop_policy().get_event_loop() call. The latter
should now raise an RuntimeError if no current event loop was set
instead of creating and setting a new event loop.

It affects also a number of asyncio functions and constructors which
call get_event_loop() implicitly: ensure_future(), shield(), gather(),
etc.

DeprecationWarning is no longer emitted if there is no running event loop but
the current event loop was set.

Co-authored-by: Łukasz Langa <lukasz@langa.pl>
This commit is contained in:
Serhiy Storchaka 2022-12-06 19:42:12 +02:00 committed by GitHub
parent b72014c783
commit fd38a2f0ec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 114 additions and 251 deletions

View file

@ -619,7 +619,7 @@ class AbstractEventLoopPolicy:
Returns an event loop object implementing the BaseEventLoop interface,
or raises an exception in case no event loop has been set for the
current context and the current policy does not specify to create one.
current context.
It should never return None."""
raise NotImplementedError
@ -672,11 +672,6 @@ class BaseDefaultEventLoopPolicy(AbstractEventLoopPolicy):
Returns an instance of EventLoop or raises an exception.
"""
if (self._local._loop is None and
not self._local._set_called and
threading.current_thread() is threading.main_thread()):
self.set_event_loop(self.new_event_loop())
if self._local._loop is None:
raise RuntimeError('There is no current event loop in thread %r.'
% threading.current_thread().name)
@ -786,16 +781,9 @@ def get_event_loop():
the result of `get_event_loop_policy().get_event_loop()` call.
"""
# NOTE: this function is implemented in C (see _asynciomodule.c)
return _py__get_event_loop()
def _get_event_loop(stacklevel=3):
current_loop = _get_running_loop()
if current_loop is not None:
return current_loop
import warnings
warnings.warn('There is no current event loop',
DeprecationWarning, stacklevel=stacklevel)
return get_event_loop_policy().get_event_loop()
@ -825,7 +813,6 @@ _py__get_running_loop = _get_running_loop
_py__set_running_loop = _set_running_loop
_py_get_running_loop = get_running_loop
_py_get_event_loop = get_event_loop
_py__get_event_loop = _get_event_loop
try:
@ -833,7 +820,7 @@ try:
# functions in asyncio. Pure Python implementation is
# about 4 times slower than C-accelerated.
from _asyncio import (_get_running_loop, _set_running_loop,
get_running_loop, get_event_loop, _get_event_loop)
get_running_loop, get_event_loop)
except ImportError:
pass
else:
@ -842,7 +829,6 @@ else:
_c__set_running_loop = _set_running_loop
_c_get_running_loop = get_running_loop
_c_get_event_loop = get_event_loop
_c__get_event_loop = _get_event_loop
if hasattr(os, 'fork'):

View file

@ -77,7 +77,7 @@ class Future:
the default event loop.
"""
if loop is None:
self._loop = events._get_event_loop()
self._loop = events.get_event_loop()
else:
self._loop = loop
self._callbacks = []
@ -413,7 +413,7 @@ def wrap_future(future, *, loop=None):
assert isinstance(future, concurrent.futures.Future), \
f'concurrent.futures.Future is expected, got {future!r}'
if loop is None:
loop = events._get_event_loop()
loop = events.get_event_loop()
new_future = loop.create_future()
_chain_future(future, new_future)
return new_future

View file

@ -125,7 +125,7 @@ class FlowControlMixin(protocols.Protocol):
def __init__(self, loop=None):
if loop is None:
self._loop = events._get_event_loop(stacklevel=4)
self._loop = events.get_event_loop()
else:
self._loop = loop
self._paused = False
@ -404,7 +404,7 @@ class StreamReader:
self._limit = limit
if loop is None:
self._loop = events._get_event_loop()
self._loop = events.get_event_loop()
else:
self._loop = loop
self._buffer = bytearray()

View file

@ -582,7 +582,7 @@ def as_completed(fs, *, timeout=None):
from .queues import Queue # Import here to avoid circular import problem.
done = Queue()
loop = events._get_event_loop()
loop = events.get_event_loop()
todo = {ensure_future(f, loop=loop) for f in set(fs)}
timeout_handle = None
@ -668,7 +668,7 @@ def _ensure_future(coro_or_future, *, loop=None):
'is required')
if loop is None:
loop = events._get_event_loop(stacklevel=4)
loop = events.get_event_loop()
try:
return loop.create_task(coro_or_future)
except RuntimeError:
@ -749,7 +749,7 @@ def gather(*coros_or_futures, return_exceptions=False):
gather won't cancel any other awaitables.
"""
if not coros_or_futures:
loop = events._get_event_loop()
loop = events.get_event_loop()
outer = loop.create_future()
outer.set_result([])
return outer