Why is loop property deprecated / what to do instead?

The loop properties of Application and Request are deprecated but the documentation doesn’t say why.

I have a function that sends data to a WebSocket. Since that function can be called from any thread, I wanted to use the loop attribute to ensure the work is submitted to the right even loop. Something like:

asyncio.run_coroutine_threadsafe(ws.send_json(data), request.app.loop)

This works fine, but the loop property is deprecated. How else can I find the loop aiohttp server is running on?


paol

    April 2

The loop properties of Application and Request are deprecated but the documentation doesn’t say why.

I have a function that sends data to a WebSocket. Since that function can be called from any thread, I wanted to use the loop attribute to ensure the work is submitted to the right even loop. Something like:

asyncio.run_coroutine_threadsafe(ws.send_json(data), request.app.loop)


This works fine, but the loop property is deprecated. How else can I find the loop aiohttp server is running on?

https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.get_event_loop

That doesn’t work, that gets the event loop of the current thread, which is the callers’ thread.

It does work, it’s magic! :slight_smile:

Within each thread, if you’re running some code inside a co-routine already, there can be only one event loop active, at least while inside some other asyncio coroutine. asyncio.get_event_loop() returns that event loop.

As long as you call asyncio.get_event_loop() from another asyncio co-routine being executed in the same thread, it will return the correct event loop.

And this is the reason why the loop parameter, everywhere, was deprecated: it really isn’t needed, and if it’s not needed, it’s noise. Code looks cleaner without it.

Of course, if you’re calling across different threads then this doesn’t work. I guess you need to do your own book-keeping of event loops.

As long as you call asyncio.get_event_loop() from another asyncio co-routine being executed in the same thread

That’s the point, the caller is not in the same thread. Like I said, asyncio.get_event_loop is not useful in this context.

And this is the reason why the loop parameter, everywhere, was deprecated: it really isn’t needed, and if it’s not needed, it’s noise. Code looks cleaner without it.

Is that really the case? From a quick look at the source I got the impression the _loop field is still used internally, it’s just the public property that was deprecated.

I meant in asyncio in general, the loop parameter has been deprecated in asyncio, aiohttp is just following the general deprecation. I found this Stack Overflow thread discussing it: https://stackoverflow.com/questions/60312374/what-are-all-these-deprecated-loop-parameters-in-asyncio

So I think you’re going to have to find another way to get the event loop. Possibly you have to store a reference to it by having some code that needs to run within the main thread inside a coroutine, which gets the event loop, stores it, and launches the producer thread giving it the loop.

def producer(loop):
   asyncio.run_coroutine_threadsafe(ws.send_json(data), request.app.loop)

async def start_my_producer():
   loop = asyncio.get_event_loop()
   my_thread = threading.Thread(target=producer, args=(loop,))
   my_thread.start()

Yeah, I suppose there is a place where I can call asyncio.get_event_loop() and save the result: in the request handler that opens the WebSocketResponse, since in that context it is guaranteed to return the same loop as the request.loop property.

Thanks.