python3.8 RuntimeError: no running event loop
You have to pass the loop
as argument to the .all_tasks()
function:
pending = asyncio.all_tasks(loop)
Output:
<_UnixSelectorEventLoop running=False closed=False debug=False>
<_GatheringFuture pending>
Results: [8, 5, 2, 9, 6, 3, ZeroDivisionError('division by zero'), 7, 4, 1]
So for a full correction of your script:
import asyncio
async def f(delay):
if delay:
await asyncio.sleep(1 / delay)
return delay
loop = asyncio.get_event_loop()
for i in range(10):
loop.create_task(f(i))
print(loop)
pending = asyncio.all_tasks(loop)
group = asyncio.gather(*pending, return_exceptions=True)
results = loop.run_until_complete(group)
print(f'Results: {results}')
loop.close()
asyncio.run() cannot be called from a running event loop when using Jupyter Notebook
The asyncio.run()
documentation says:
This function cannot be called when another asyncio event loop is running in the same thread.
In your case, jupyter (IPython ≥ 7.0) is already running an event loop:
You can now use async/await at the top level in the IPython terminal and in the notebook, it should — in most of the cases — “just work”. Update IPython to version 7+, IPykernel to version 5+, and you’re off to the races.
Therefore you don't need to start the event loop yourself and can instead call await main(url)
directly, even if your code lies outside any asynchronous function.
Jupyter / IPython
async def main():
print(1)
await main()
Python (≥ 3.7) or older versions of IPython
import asyncio
async def main():
print(1)
asyncio.run(main())
In your code that would give:
url = ['url1', 'url2']
result = await main(url)
for text in result:
pass # text contains your html (text) response
Caution
There is a slight difference on how Jupyter uses the loop compared to IPython.
When running my Discord bot I get a RuntimeError: no running event loop {FIXED}
Your initialization of a loop is wrong, it should be:
client.loop.create_task(lightswitch_task())
client.loop.create_task(version_update_background_task())
client.run()
Python create_task does not work in running event loop
When creating task from outside the event loop thread, you need to use asyncio.run_coroutine_threadsafe
. That function will schedule the coroutine in a thread-safe manner and notify the event loop that there is new work to be done. It will also return a concurrent.futures.Future
object which you can use to block the current thread until the result is available.
From surface it looks like tasks created in running event loop do not get executed. But why is that?
Calling create_task
is insufficient because it doesn't contain code to "wake up" the event loop. This is a feature - such wakeup is normally not needed, and adding it would just slow down the regular single-threaded use. When create_task
is invoked from the event loop thread, it is inside an event loop callback, so the event loop can check its task queue as soon as it regains control, when it is done executing the callback. But when create_task
is invoked from a different thread, the event loop is asleep waiting for IO, so run_coroutine_threadsafe
is needed to wake it up.
To test this, you can create a "heartbeat" coroutine, which only contains an infinite loop that prints something and awaits asyncio.sleep(1)
. You'll see that the tasks created with create_task
get executed along with the heartbeat, which also happens to wake up the event loop. In busy asyncio applications this effect can give the impression that create_task
from another thread "works". However, this should never be relied on, as create_task
fails to implement proper locking and could corrupt the event loop internals.
I have not seen anything regarding this in documentation.
Take a look at the concurrency and multithreading section.
Discord Bot Asynchronous Loop Failure
To start a task you need a running event loop.
If you want to use run()
, you can start the task in setup_hook
where all your async setup should be unless it is cog specific in which case you can put them in cog_load
:
from typing import Any
class MyClient(discord.Client):
def __init__(self, *, intents: discord.Intents, **options: Any) -> None:
super().__init__(intents=intents, **options)
async def setup_hook(self) -> None:
channelname.start()
client = MyClient(intents=discord.Intents.default())
client.run('bot token')
or:
import asyncio
async def main():
async with client:
channelname.start()
await client.start('bot token')
asyncio.run(main())
Also, in your task you are operating on two offset-aware and naive datetime objects which is not allowed, you are probably getting an error but since you don't have an error handler setup it's getting eaten by it.
Do this instead:
msg_secs = (datetime.datetime.now().timestamp() - message.created_at.timestamp())
Instead of flatten()
, use this, if you are on 2.0:
messages = [message async for message in channel.history(limit=2)]
Related Topics
How to Import the Class Within the Same Directory or Sub Directory
How to Remove List Elements in a For Loop in Python
Pyaudio Installation Error - 'Command 'Gcc' Failed with Exit Status 1'
Command 'X86_64-Linux-Gnu-Gcc' Failed with Exit Status 1
Which Command to Use for Checking Whether Python Is 64Bit or 32Bit
Writing to Shared Memory in Python Is Very Slow
Python Program with Notification in Gnome Shell Doesn't Work
How to Split My 800X480 5-Inch Screen into 2 Parts
Python Requests Json Returns Single Quote
Fitting Empirical Distribution to Theoretical Ones With Scipy (Python)
Beautiful Soup: 'Resultset' Object Has No Attribute 'Find_All'
Get Local Network Interface Addresses Using Only Proc
Redirecting Python's Stdout to the File Fails with Unicodeencodeerror
How to Get Each Dependent Command Execution Output Using Paramiko Exec_Command