CPython: I don't understand the Python implementation of asyncio.events._py__get_running_loop

Tried to get some understanding of the implementation of the asyncio module. After reading some parts of the code of events.py I noticed the code of the lines get_running_loop python implementation. Among other things, this code says, # NOTE: this function is implemented in C (see _asynciomodule.c) for the functions _get_running_loop and get_running_loop. After reading on, I discovered at the bottom of events.py some alias to the pure Python implementations for testing purposes. Getting curious I tried the following script below:

import asyncio

async def main():
    print(type(asyncio.events._py__get_running_loop))
    # print(type(asyncio.events._get_running_loop))
    loop = asyncio.events._py__get_running_loop()
    # loop = asyncio.events._get_running_loop()
    print(loop)
    print(type(loop))

asyncio.run(main(), debug=True)

Running the code above I get:

<class 'builtin_function_or_method'>
<_UnixSelectorEventLoop running=True closed=False debug=True>
<class 'asyncio.unix_events._UnixSelectorEventLoop'>

and after commenting out the C implementation and testing the pure Python implementation I get:

<class 'function'>
None
<class 'NoneType'>

I did expect this result, but I don’t really understand the rationale behind this pure-Python implementation.

So, my question is: What was the reason to have this pure-Python implementation, and how to use it to get non-trivial results (i.e. an event loop)?

I’m glad at any help. I want to improve, so if this question is not appropriate in this forum → please tell me.

Well, you’d need to swap out _set_running_loop() also, so the pure-Python variable is set when a loop runs. Actually a better method would be to set sys.modules['_asyncio'] = None before importing, which makes importing the C module fail.

The reason the C implementation exists is for speed - get_running_loop() was identified as being called extremely often, so reimplementing it in C was worth it to speed up async code. The reason the pure-Python version exists is explained in PEP 399 - there’s other implementations of the Python interpreter out there like PyPy and MicroPython, which may not support the C-API. Since the pure-Python code is present and tested to ensure it works, those other implementations can simply copy in the asyncio package and have it work immediately.

1 Like

Thanks a lot! Understood, and learned quite a bit.