classification
Title: Non indemnpotent behavior of asyncio.get_event_loop and asyncio.run sequence.
Type: behavior Stage:
Components: asyncio Versions: Python 3.9, Python 3.8, Python 3.7
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: asvetlov, mbussonn, yselivanov
Priority: normal Keywords:

Created on 2019-12-02 18:39 by mbussonn, last changed 2019-12-06 11:04 by asvetlov.

Messages (4)
msg357727 - (view) Author: Matthias Bussonnier (mbussonn) * Date: 2019-12-02 18:39
Hi, Not sure if this a bug, or an intended feature. 
I got surprise by the following behavior. 


    from asyncio import run, sleep, get_event_loop

    print(get_event_loop()) # return the current eventloop
    run(sleep(0))
    print(get_event_loop()) # raise a RuntimeError


I would expect `get_event_loop` to get back to it's initial default value. 

This comes from the fact that `run()` call `set_event_loop()` to `None`. with
both sets `_set_called` to `True`, but `get_event_loop` seem to assume if
_set_called is True, then loop cannot be none. 

I'm tempted to think that if `set_loop()` is called with `None`, it should reset the `_set_called` to False. Or Am I supposed to call `set_event_loop(new_event_loop())` myself ? 

I'm likely missing  something so any insight would be appreciated; if you
believe this is an actual issue I'm happy to send a PR.
msg357748 - (view) Author: Andrew Svetlov (asvetlov) * (Python committer) Date: 2019-12-03 10:42
I think now it is too late for changing the behavior.
In the ideal world, get_event_loop() should never exist, maybe we can deprecate/remove it eventually.
run() should be used for executing async code; get_running_loop() for getting a reference to the currently executed loop.
It may help to avoid many silly problems.
Maybe some scenarios are not covered but at least high-level code can be organized this way.

P.S.
set_event_loop(None) is not for resetting to default but for disabling of the default loop creation for the current thread. Non-main threads work like set_event_loop(None) was called implicitly.
msg357865 - (view) Author: Matthias Bussonnier (mbussonn) * Date: 2019-12-05 16:47
Thanks Andrew; 

I'd still would love to have a way to get the current eventloop outside of async code that is consistent. 

I guess throwing an error with `get_event_loop()` is ok, it's just that `RuntimeError` feel like a weird thing to catch.

Alternatively is the current event loop is None I feel like returning None would also make sens imho. 

Feel free to close if you think this will not get fixed/updated.
msg357910 - (view) Author: Andrew Svetlov (asvetlov) * (Python committer) Date: 2019-12-06 11:04
Asyncio has a few own exceptions, the library tries to utilize existing ones, e.g. ValueError, TypeError, and OSError family. RuntimeError falls into this category.

get_event_loop() never returns None, it was from very beginning. If we change it existing third-party code will be broken. So, no way, sorry.

I really don't think we can change anything here.

Would you describe cases when you need an implicit loop instance but there is no running loop currently?
History
Date User Action Args
2019-12-06 11:04:05asvetlovsetmessages: + msg357910
2019-12-05 16:47:36mbussonnsetmessages: + msg357865
2019-12-03 10:42:52asvetlovsetmessages: + msg357748
2019-12-02 18:39:47mbussonncreate