Skip to content

Commit 9fce906

Browse files
gh-127949: deprecate asyncio.set_event_loop (#128218)
Deprecate `asyncio.set_event_loop` to be removed in Python 3.16.
1 parent 3ddd70c commit 9fce906

16 files changed

+77
-55
lines changed

Doc/library/asyncio-eventloop.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ an event loop:
6666

6767
Set *loop* as the current event loop for the current OS thread.
6868

69+
.. deprecated:: next
70+
The :func:`set_event_loop` function is deprecated and will be removed
71+
in Python 3.16.
72+
6973
.. function:: new_event_loop()
7074

7175
Create and return a new event loop object.

Lib/asyncio/__main__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ def interrupt(self) -> None:
149149

150150
return_code = 0
151151
loop = asyncio.new_event_loop()
152-
asyncio.set_event_loop(loop)
152+
asyncio._set_event_loop(loop)
153153

154154
repl_locals = {'asyncio': asyncio}
155155
for key in {'__name__', '__package__',

Lib/asyncio/events.py

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,22 @@
55
# SPDX-FileCopyrightText: Copyright (c) 2015-2021 MagicStack Inc. http://magic.io
66

77
__all__ = (
8-
'_AbstractEventLoopPolicy',
9-
'AbstractEventLoop', 'AbstractServer',
10-
'Handle', 'TimerHandle',
11-
'_get_event_loop_policy',
12-
'get_event_loop_policy',
13-
'_set_event_loop_policy',
14-
'set_event_loop_policy',
15-
'get_event_loop', 'set_event_loop', 'new_event_loop',
16-
'_set_running_loop', 'get_running_loop',
17-
'_get_running_loop',
8+
"_AbstractEventLoopPolicy",
9+
"AbstractEventLoop",
10+
"AbstractServer",
11+
"Handle",
12+
"TimerHandle",
13+
"_get_event_loop_policy",
14+
"get_event_loop_policy",
15+
"_set_event_loop_policy",
16+
"set_event_loop_policy",
17+
"get_event_loop",
18+
"_set_event_loop",
19+
"set_event_loop",
20+
"new_event_loop",
21+
"_set_running_loop",
22+
"get_running_loop",
23+
"_get_running_loop",
1824
)
1925

2026
import contextvars
@@ -801,9 +807,13 @@ def get_event_loop():
801807
return _get_event_loop_policy().get_event_loop()
802808

803809

810+
def _set_event_loop(loop):
811+
_get_event_loop_policy().set_event_loop(loop)
812+
804813
def set_event_loop(loop):
805814
"""Equivalent to calling get_event_loop_policy().set_event_loop(loop)."""
806-
_get_event_loop_policy().set_event_loop(loop)
815+
warnings._deprecated('asyncio.set_event_loop', remove=(3,16))
816+
_set_event_loop(loop)
807817

808818

809819
def new_event_loop():

Lib/asyncio/runners.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ def close(self):
7474
loop.shutdown_default_executor(constants.THREAD_JOIN_TIMEOUT))
7575
finally:
7676
if self._set_event_loop:
77-
events.set_event_loop(None)
77+
events._set_event_loop(None)
7878
loop.close()
7979
self._loop = None
8080
self._state = _State.CLOSED
@@ -147,7 +147,7 @@ def _lazy_init(self):
147147
if not self._set_event_loop:
148148
# Call set_event_loop only once to avoid calling
149149
# attach_loop multiple times on child watchers
150-
events.set_event_loop(self._loop)
150+
events._set_event_loop(self._loop)
151151
self._set_event_loop = True
152152
else:
153153
self._loop = self._loop_factory()

Lib/test/test_asyncgen.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,7 @@ class AsyncGenAsyncioTest(unittest.TestCase):
624624

625625
def setUp(self):
626626
self.loop = asyncio.new_event_loop()
627-
asyncio.set_event_loop(None)
627+
asyncio._set_event_loop(None)
628628

629629
def tearDown(self):
630630
self.loop.close()

Lib/test/test_asyncio/functional.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def loop_exception_handler(self, loop, context):
2424

2525
def setUp(self):
2626
self.loop = self.new_loop()
27-
asyncio.set_event_loop(None)
27+
asyncio._set_event_loop(None)
2828

2929
self.loop.set_exception_handler(self.loop_exception_handler)
3030
self.__unhandled_exceptions = []
@@ -39,7 +39,7 @@ def tearDown(self):
3939
self.fail('unexpected calls to loop.call_exception_handler()')
4040

4141
finally:
42-
asyncio.set_event_loop(None)
42+
asyncio._set_event_loop(None)
4343
self.loop = None
4444

4545
def tcp_server(self, server_prog, *,

Lib/test/test_asyncio/test_base_events.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -331,10 +331,10 @@ def check_in_thread(loop, event, debug, create_loop, fut):
331331
if create_loop:
332332
loop2 = base_events.BaseEventLoop()
333333
try:
334-
asyncio.set_event_loop(loop2)
334+
asyncio._set_event_loop(loop2)
335335
self.check_thread(loop, debug)
336336
finally:
337-
asyncio.set_event_loop(None)
337+
asyncio._set_event_loop(None)
338338
loop2.close()
339339
else:
340340
self.check_thread(loop, debug)
@@ -690,7 +690,7 @@ def default_exception_handler(self, context):
690690

691691
loop = Loop()
692692
self.addCleanup(loop.close)
693-
asyncio.set_event_loop(loop)
693+
asyncio._set_event_loop(loop)
694694

695695
def run_loop():
696696
def zero_error():
@@ -1983,7 +1983,7 @@ def stop_loop_cb(loop):
19831983
async def stop_loop_coro(loop):
19841984
loop.stop()
19851985

1986-
asyncio.set_event_loop(self.loop)
1986+
asyncio._set_event_loop(self.loop)
19871987
self.loop.set_debug(True)
19881988
self.loop.slow_callback_duration = 0.0
19891989

Lib/test/test_asyncio/test_events.py

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ async def doit():
5858
return 'hello'
5959

6060
loop = asyncio.new_event_loop()
61-
asyncio.set_event_loop(loop)
61+
asyncio._set_event_loop(loop)
6262
return loop.run_until_complete(doit())
6363

6464

@@ -2695,6 +2695,14 @@ async def inner():
26952695

26962696
class PolicyTests(unittest.TestCase):
26972697

2698+
def test_asyncio_set_event_loop_deprecation(self):
2699+
with self.assertWarnsRegex(
2700+
DeprecationWarning, "'asyncio.set_event_loop' is deprecated"):
2701+
loop = asyncio.new_event_loop()
2702+
asyncio.set_event_loop(loop)
2703+
self.assertIs(loop, asyncio.get_event_loop())
2704+
loop.close()
2705+
26982706
def test_abstract_event_loop_policy_deprecation(self):
26992707
with self.assertWarnsRegex(
27002708
DeprecationWarning, "'asyncio.AbstractEventLoopPolicy' is deprecated"):
@@ -2824,14 +2832,14 @@ def setUp(self):
28242832
super().setUp()
28252833

28262834
self.loop = asyncio.new_event_loop()
2827-
asyncio.set_event_loop(self.loop)
2835+
asyncio._set_event_loop(self.loop)
28282836

28292837
def tearDown(self):
28302838
try:
28312839
super().tearDown()
28322840
finally:
28332841
self.loop.close()
2834-
asyncio.set_event_loop(None)
2842+
asyncio._set_event_loop(None)
28352843

28362844
events._get_running_loop = self._get_running_loop_saved
28372845
events._set_running_loop = self._set_running_loop_saved
@@ -2885,7 +2893,7 @@ def get_event_loop(self):
28852893

28862894
with self.assertRaises(TestError):
28872895
asyncio.get_event_loop()
2888-
asyncio.set_event_loop(None)
2896+
asyncio._set_event_loop(None)
28892897
with self.assertRaises(TestError):
28902898
asyncio.get_event_loop()
28912899

@@ -2900,10 +2908,10 @@ async def func():
29002908

29012909
loop.run_until_complete(func())
29022910

2903-
asyncio.set_event_loop(loop)
2911+
asyncio._set_event_loop(loop)
29042912
with self.assertRaises(TestError):
29052913
asyncio.get_event_loop()
2906-
asyncio.set_event_loop(None)
2914+
asyncio._set_event_loop(None)
29072915
with self.assertRaises(TestError):
29082916
asyncio.get_event_loop()
29092917

@@ -2927,7 +2935,7 @@ def test_get_event_loop_returns_running_loop2(self):
29272935
with self.assertRaisesRegex(RuntimeError, 'no current'):
29282936
asyncio.get_event_loop()
29292937

2930-
asyncio.set_event_loop(None)
2938+
asyncio._set_event_loop(None)
29312939
with self.assertRaisesRegex(RuntimeError, 'no current'):
29322940
asyncio.get_event_loop()
29332941

@@ -2938,10 +2946,10 @@ async def func():
29382946

29392947
loop.run_until_complete(func())
29402948

2941-
asyncio.set_event_loop(loop)
2949+
asyncio._set_event_loop(loop)
29422950
self.assertIs(asyncio.get_event_loop(), loop)
29432951

2944-
asyncio.set_event_loop(None)
2952+
asyncio._set_event_loop(None)
29452953
with self.assertRaisesRegex(RuntimeError, 'no current'):
29462954
asyncio.get_event_loop()
29472955

Lib/test/test_asyncio/test_futures.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,8 @@ async def test():
178178

179179
def test_constructor_use_global_loop(self):
180180
# Deprecated in 3.10, undeprecated in 3.12
181-
asyncio.set_event_loop(self.loop)
182-
self.addCleanup(asyncio.set_event_loop, None)
181+
asyncio._set_event_loop(self.loop)
182+
self.addCleanup(asyncio._set_event_loop, None)
183183
f = self._new_future()
184184
self.assertIs(f._loop, self.loop)
185185
self.assertIs(f.get_loop(), self.loop)
@@ -566,8 +566,8 @@ async def test():
566566

567567
def test_wrap_future_use_global_loop(self):
568568
# Deprecated in 3.10, undeprecated in 3.12
569-
asyncio.set_event_loop(self.loop)
570-
self.addCleanup(asyncio.set_event_loop, None)
569+
asyncio._set_event_loop(self.loop)
570+
self.addCleanup(asyncio._set_event_loop, None)
571571
def run(arg):
572572
return (arg, threading.get_ident())
573573
ex = concurrent.futures.ThreadPoolExecutor(1)

Lib/test/test_asyncio/test_streams.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def _basetest_open_connection_no_loop_ssl(self, open_connection_fut):
7171
try:
7272
reader, writer = self.loop.run_until_complete(open_connection_fut)
7373
finally:
74-
asyncio.set_event_loop(None)
74+
asyncio._set_event_loop(None)
7575
writer.write(b'GET / HTTP/1.0\r\n\r\n')
7676
f = reader.read()
7777
data = self.loop.run_until_complete(f)
@@ -839,8 +839,8 @@ def test_streamreader_constructor_use_global_loop(self):
839839
# asyncio issue #184: Ensure that StreamReaderProtocol constructor
840840
# retrieves the current loop if the loop parameter is not set
841841
# Deprecated in 3.10, undeprecated in 3.12
842-
self.addCleanup(asyncio.set_event_loop, None)
843-
asyncio.set_event_loop(self.loop)
842+
self.addCleanup(asyncio._set_event_loop, None)
843+
asyncio._set_event_loop(self.loop)
844844
reader = asyncio.StreamReader()
845845
self.assertIs(reader._loop, self.loop)
846846

@@ -863,8 +863,8 @@ def test_streamreaderprotocol_constructor_use_global_loop(self):
863863
# asyncio issue #184: Ensure that StreamReaderProtocol constructor
864864
# retrieves the current loop if the loop parameter is not set
865865
# Deprecated in 3.10, undeprecated in 3.12
866-
self.addCleanup(asyncio.set_event_loop, None)
867-
asyncio.set_event_loop(self.loop)
866+
self.addCleanup(asyncio._set_event_loop, None)
867+
asyncio._set_event_loop(self.loop)
868868
reader = mock.Mock()
869869
protocol = asyncio.StreamReaderProtocol(reader)
870870
self.assertIs(protocol._loop, self.loop)

Lib/test/test_asyncio/test_tasks.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,8 @@ async def test():
212212
self.assertEqual(t.result(), 'ok')
213213

214214
# Deprecated in 3.10, undeprecated in 3.12
215-
asyncio.set_event_loop(self.loop)
216-
self.addCleanup(asyncio.set_event_loop, None)
215+
asyncio._set_event_loop(self.loop)
216+
self.addCleanup(asyncio._set_event_loop, None)
217217
t = asyncio.ensure_future(notmuch())
218218
self.assertIs(t._loop, self.loop)
219219
self.loop.run_until_complete(t)
@@ -2202,8 +2202,8 @@ def test_shield_coroutine_use_global_loop(self):
22022202
async def coro():
22032203
return 42
22042204

2205-
asyncio.set_event_loop(self.loop)
2206-
self.addCleanup(asyncio.set_event_loop, None)
2205+
asyncio._set_event_loop(self.loop)
2206+
self.addCleanup(asyncio._set_event_loop, None)
22072207
outer = asyncio.shield(coro())
22082208
self.assertEqual(outer._loop, self.loop)
22092209
res = self.loop.run_until_complete(outer)
@@ -2273,7 +2273,7 @@ async def kill_me(loop):
22732273

22742274
self.assertEqual(self.all_tasks(loop=self.loop), {task})
22752275

2276-
asyncio.set_event_loop(None)
2276+
asyncio._set_event_loop(None)
22772277

22782278
# execute the task so it waits for future
22792279
self.loop._run_once()
@@ -3278,8 +3278,8 @@ async def gather():
32783278

32793279
def test_constructor_empty_sequence_use_global_loop(self):
32803280
# Deprecated in 3.10, undeprecated in 3.12
3281-
asyncio.set_event_loop(self.one_loop)
3282-
self.addCleanup(asyncio.set_event_loop, None)
3281+
asyncio._set_event_loop(self.one_loop)
3282+
self.addCleanup(asyncio._set_event_loop, None)
32833283
fut = asyncio.gather()
32843284
self.assertIsInstance(fut, asyncio.Future)
32853285
self.assertIs(fut._loop, self.one_loop)
@@ -3386,8 +3386,8 @@ def test_constructor_use_global_loop(self):
33863386
# Deprecated in 3.10, undeprecated in 3.12
33873387
async def coro():
33883388
return 'abc'
3389-
asyncio.set_event_loop(self.other_loop)
3390-
self.addCleanup(asyncio.set_event_loop, None)
3389+
asyncio._set_event_loop(self.other_loop)
3390+
self.addCleanup(asyncio._set_event_loop, None)
33913391
gen1 = coro()
33923392
gen2 = coro()
33933393
fut = asyncio.gather(gen1, gen2)

Lib/test/test_asyncio/test_unix_events.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,11 +1116,11 @@ class TestFunctional(unittest.TestCase):
11161116

11171117
def setUp(self):
11181118
self.loop = asyncio.new_event_loop()
1119-
asyncio.set_event_loop(self.loop)
1119+
asyncio._set_event_loop(self.loop)
11201120

11211121
def tearDown(self):
11221122
self.loop.close()
1123-
asyncio.set_event_loop(None)
1123+
asyncio._set_event_loop(None)
11241124

11251125
def test_add_reader_invalid_argument(self):
11261126
def assert_raises():

Lib/test/test_asyncio/utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@ def set_event_loop(self, loop, *, cleanup=True):
541541
if loop is None:
542542
raise AssertionError('loop is None')
543543
# ensure that the event loop is passed explicitly in asyncio
544-
events.set_event_loop(None)
544+
events._set_event_loop(None)
545545
if cleanup:
546546
self.addCleanup(self.close_loop, loop)
547547

@@ -554,7 +554,7 @@ def setUp(self):
554554
self._thread_cleanup = threading_helper.threading_setup()
555555

556556
def tearDown(self):
557-
events.set_event_loop(None)
557+
events._set_event_loop(None)
558558

559559
# Detect CPython bug #23353: ensure that yield/yield-from is not used
560560
# in an except block of a generator

Lib/test/test_coroutines.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2287,7 +2287,7 @@ async def f():
22872287
buffer.append('unreachable')
22882288

22892289
loop = asyncio.new_event_loop()
2290-
asyncio.set_event_loop(loop)
2290+
asyncio._set_event_loop(loop)
22912291
try:
22922292
loop.run_until_complete(f())
22932293
except MyException:

Lib/test/test_type_params.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1060,7 +1060,7 @@ async def coroutine[B]():
10601060

10611061
co = get_coroutine()
10621062

1063-
self.addCleanup(asyncio.set_event_loop_policy, None)
1063+
self.addCleanup(asyncio._set_event_loop_policy, None)
10641064
a, b = asyncio.run(co())
10651065

10661066
self.assertIsInstance(a, TypeVar)

Lib/test/test_unittest/test_async_case.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ async def cleanup(self, fut):
476476
def test_setup_get_event_loop(self):
477477
# See https://github.com/python/cpython/issues/95736
478478
# Make sure the default event loop is not used
479-
asyncio.set_event_loop(None)
479+
asyncio._set_event_loop(None)
480480

481481
class TestCase1(unittest.IsolatedAsyncioTestCase):
482482
def setUp(self):

0 commit comments

Comments
 (0)