What are all these deprecated "loop" parameters in asyncio?

Maxpm :

A lot of the functions in asyncio have deprecated loop parameters, scheduled to be removed in Python 3.10. Examples include as_completed(), sleep(), and wait().

I'm looking for some historical context on these parameters and their removal.

  • What problems did loop solve? Why would one have used it in the first place?
  • What was wrong with loop? Why is it being removed en masse?
  • What replaces loop, now that it's gone?
user4815162342 :

What problems did loop solve? Why would one have used it in the first place?

Prior to Python 3.6, asyncio.get_event_loop() was not guaranteed to return the event loop currently running when called from an asyncio coroutine or callback. It would return whatever event loop was previously set using set_event_loop(some_loop), or the one automatically created by asyncio. But sync code could easily creat a different loop with another_loop = asyncio.new_event_loop() and spin it up using another_loop.run_until_complete(some_coroutine()). In this scenario, get_event_loop() called inside the some_coroutine() and the coroutines it awaits would return some_loop rather than another_loop. This kind of thing wouldn't happen in casual uses of asyncio, but it had to be handled by async libraries which couldn't just assume exactly how the top-level coroutine was invoked. (For example, in tests or in some usages involving threads, one might want to spin up an event loop without disturbing the global setting with set_event_loop.) The libraries would offer the explicit loop argument where you'd pass another_loop in the above case, or in any other case where the loop you are running differs from the loop set up with asyncio.set_event_loop().

This issue would be fixed in Python 3.6 and 3.5.3, where get_event_loop() was modified to reliably return the running loop if called from inside one, returning another_loop in the above scenario. Python 3.7 would additionally introduced get_running_loop() which completely ignores the global setting and always returns the currently running loop, raising an exception if not inside one. See this thread for the original discussion.

Once get_event_loop() became reliable, another problem was that of performance. Since the event loop was needed for some very frequently used calls, most notably call_soon, it was simply more efficient to pass around and cache the loop object. Asyncio itself did that, and many libraries followed suit. Eventually get_event_loop() was accelerated in C and was no longer a bottleneck.

These two changes made the loop arguments no longer necessary. Now we can take a look why they are being removed.

What was wrong with loop? Why is it being removed en masse?

It complicates the API and opens up possibilities for errors. Async code should almost never just randomly communicate with a different loop, and now that get_event_loop() is both correct and fast, there is no reason not to use it.

Also, passing the loop through all the layers of abstraction of a typical application is simply tedious. Now that many other languages have async/await, it has become clear that explicitly passing around a global object is not ergonomic and should not be required from programmers.

What replaces loop, now that it's gone?

Just use get_event_loop() to get the loop when you need it. Alternatively, one can use get_running_loop() to assert that a loop is running.

The need for accessing the event loop is somewhat reduced in Python 3.7, as some functions that were previously only available as methods on the loop, such as create_task, are now available as stand-alone functions.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=5180&siteId=1