`RuntimeError: no running event loop` after upgrading to 0.5.0
martyanov opened this issue · comments
Unfortunately, changes in #246 broke the code that relies on creating an instance of janus.Queue
outside of the scope of a running event loop, for no obvious reason.
Also, the behavior now contradicts with the behavior of asyncio.Queue
.
>>> import asyncio
>>> asyncio.Queue()
<Queue at 0x7f76be085730 maxsize=0>
>>> import janus
>>> janus.Queue()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/user/projects/project/.venv/lib64/python3.8/site-packages/janus/__init__.py", line 29, in __init__
self._loop = current_loop()
RuntimeError: no running event loop
Is there any good reason to not just use asyncio.get_event_loop
? From performance perspective it shouldn't be significant.
In Python 3.8 and upwards, passing loop arguments to manay asyncio objects (including Queue
) are marked to be deprecated.
In asyncio, the explicit passing of a loop argument has been deprecated and will be removed in version 3.10 for the following: asyncio.sleep(), asyncio.gather(), asyncio.shield(), asyncio.wait_for(), asyncio.wait(), asyncio.as_completed(), asyncio.Task, asyncio.Lock, asyncio.Event, asyncio.Condition, asyncio.Semaphore, asyncio.BoundedSemaphore, asyncio.Queue, asyncio.create_subprocess_exec(), and asyncio.create_subprocess_shell().
This means that instantiation of these objects outside the event loop (i.e., there is no running event loop in the current thread && the current line of code is not ultimately executed from a coroutine bound to a specific event loop) is now prohibited.
I think janus
shoud follow the same behavior for consistency and to avoid deprecation warnings.
So, the new, intended way of use is to create janus/asyncio queues in a coroutine and lazily refer them in the synchronous counterparts.
Note that, asyncio.get_event_loop()
implicitly creates a new event loop if there is no one, and this often causes having two event loops if the user code explicitly creates another one later.
This is usually not what people want and may cause undefined behaviors.
The new API, asyncio.get_running_loop()
is now preferred across all asyncio-based codes, which generates an explicit error when there is no current event loop. All asyncio functions and classes are recommended to use it and the standard asyncio library is also migrating.
Are there any proofs that asyncio.get_event_loop
will be replaced with asyncio.get_running_loop
in asyncio.Queue
, for example? I mean this will be refactored to use asyncio.get_running_loop
. Deprecating and removing the loop
argement is ok, but changing the internal behavior will break a lot of people's code.
All that is stated now is The loop argument is deprecated since Python 3.8, and scheduled for removal in Python 3.10.
and many people think that their project is ready for upgrade, because they are not relying on explicit loop
argument, but probably it will still break.
I understand the reasoning behind the changes, but the consequences are not that obvious at all.
The reason is: Queue does not exist without the loop.
The current version makes this dependency strict and explicit.
Sorry, this is not going to change