create_connection() method in Python asyncio module

Viewed 696

The document mentions that AbstractEventLoop.create_connection, on successful execution, will return a (transport, protocol) tuple. However all the examples show that it returns coroutine.

The code also shows that it does return (transport, protocol) tuple. Could you help on this?

1 Answers

Both observations are true: create_connection is a coroutine function that returns a transport, protocol pair. But to get a hold of that return value, you need to await the coroutine (if in an async def) or use loop.run_until_complete (if in synchronous code).

If you just call a coroutine function without awaiting the result, what you get is a coroutine object that you can pass around and await later. This is analogous to how just calling a generator function just returns a generator-iterator; to actually get values out of it, you must exhaust it with a for loop.

Many examples don't really need the return value, so they only store the returned coroutine object in a local variable coro and then run run_until_complete(coro), effectively discarding the returned transport/protocol pair. The full usage is shown for example in 19.5.4.3.5:

connect_coro = loop.create_connection(MyProtocol, sock=rsock)
transport, protocol = loop.run_until_complete(connect_coro)

I believe much of the confusion would disappear if that and other examples were formulated along the lines of:

transport, protocol = loop.run_until_complete(
    loop.create_connection(MyProtocol, sock=rsock))

That makes it clearer that create_connection returns a pair, and that you need run_until_complete (the sync equivalent of await) to access it, the latter being the case with every coroutine or asyncio future.

Related