How to await Tasks created inside an endless loop in asyncio - python-asyncio

I want to create tasks programatically inside the running loop. Every second will be check if some tasks are currently not running (sometimes because of exceptions) the should be started. For simplicity reasons here ist only the loop.
import asyncio
async def parent_coro():
await child_coro()
async def child_coro():
await asyncio.sleep(1)
raise Exception('OMG!')
async def main():
tasks = []
while True:
task = asyncio.create_task(parent_coro()),
tasks.append(task)
await asyncio.sleep(1)
# This cannot be reached
done, pending = await asyncio.wait(tasks)
for task in done:
try:
print(task.exception())
except Exception:
print('You will not see me!')
if __name__ == '__main__':
asyncio.run(main())
The problem is that this Tasks cannot be awaited, and when I stop the process (Ctrl+C) I get Task exception was never retrieved. Here the stacktrace:
^CTraceback (most recent call last):
File "/tmp/check.py", line 33, in <module>
asyncio.run(main())
File "/home/antonio/.pyenv/versions/3.9.6/lib/python3.9/asyncio/runners.py", line 44, in run
return loop.run_until_complete(main)
File "/home/antonio/.pyenv/versions/3.9.6/lib/python3.9/asyncio/base_events.py", line 629, in run_until_complete
self.run_forever()
File "/home/antonio/.pyenv/versions/3.9.6/lib/python3.9/asyncio/base_events.py", line 596, in run_forever
self._run_once()
File "/home/antonio/.pyenv/versions/3.9.6/lib/python3.9/asyncio/base_events.py", line 1854, in _run_once
event_list = self._selector.select(timeout)
File "/home/antonio/.pyenv/versions/3.9.6/lib/python3.9/selectors.py", line 469, in select
fd_event_list = self._selector.poll(timeout, max_ev)
KeyboardInterrupt
Task exception was never retrieved
future: <Task finished name='Task-6' coro=<parent_coro() done, defined at /home/myproject/check.py:4> exception=Exception('OMG!')>
Traceback (most recent call last):
File "/tmp/check.py", line 5, in parent_coro
await child_coro()
File "/tmp/check.py", line 10, in child_coro
raise Exception('OMG!')
Exception: OMG!
Task exception was never retrieved
future: <Task finished name='Task-5' coro=<parent_coro() done, defined at /tmp/check.py:4> exception=Exception('OMG!')>
Traceback (most recent call last):
File "/tmp/check.py", line 5, in parent_coro
await child_coro()
File "/tmp/check.py", line 10, in child_coro
raise Exception('OMG!')
Exception: OMG!
Task exception was never retrieved
future: <Task finished name='Task-4' coro=<parent_coro() done, defined at /tmp/check.py:4> exception=Exception('OMG!')>
Traceback (most recent call last):
File "/tmp/check.py", line 5, in parent_coro
await child_coro()
File "/tmp/check.py", line 10, in child_coro
raise Exception('OMG!')
Exception: OMG!
Task exception was never retrieved
future: <Task finished name='Task-3' coro=<parent_coro() done, defined at /home/myproject/check.py:4> exception=Exception('OMG!')>
Traceback (most recent call last):
File "/home/myproject/check.py", line 5, in parent_coro
await child_coro()
File "/home/myproject/check.py", line 10, in child_coro
raise Exception('OMG!')
Exception: OMG!
Task exception was never retrieved
future: <Task finished name='Task-2' coro=<parent_coro() done, defined at /home/myproject/check.py:4> exception=Exception('OMG!')>
Traceback (most recent call last):
File "/home/myproject/check.py", line 5, in parent_coro
await child_coro()
File "/home/myproject/check.py", line 10, in child_coro
raise Exception('OMG!')
Exception: OMG!

There is now way for your code to exit the while loop.
As a solution, you can inspect your tasks inside the while loop. Your tasks will then be inspected every second.
async def main():
tasks = []
while True:
task = asyncio.create_task(parent_coro()),
tasks.append(task)
await asyncio.sleep(1)
done, pending = await asyncio.wait(tasks)
for task in done:
try:
print(task.exception())
except Exception:
print('You will not see me!)
You could also create a background task launching parent_coro tasks every second. In this case, once this task is launched, you could check tasks whenever you want.

Related

Discord.py new timeout command error: "AttributeError: 'User' object has no attribute 'timeout_for'"

Hello all and happy new year 2022!!
Since the recent add of "timeouts" for discord, I have tried to make the timeout command following some tutorials like:
https://docs.pycord.dev/en/master/api.html?highlight=timeout#discord.Member.timeout
https://youtu.be/c5V4OaTNDtM
But I may get the following error for a reason I don't know:
Ignoring exception in command timeout2:
Traceback (most recent call last):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 85, in wrapped
ret = await coro(*args, **kwargs)
File "/home/runner/Russia-Bot/moderator.py", line 42, in timeout2
await member.timeout_for(time)
AttributeError: 'Member' object has no attribute 'timeout_for'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/bot.py", line 939, in invoke
await ctx.command.invoke(ctx)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 863, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 94, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'Member' object has no attribute 'timeout_for'
Here's the command code, i have made 2 different commands but both give the same issue:
Variant 1:
#client.command()
async def timeout(ctx, member: discord.Member, time=None, reason=None):
time = humanfriendly.parse_timespan(time)
await member.timeout(until = discord.utils.utcnow() + datetime.timedelta(seconds=time), reason=reason)
await ctx.send (f"{member} callate un rato anda {time}")
Variant 2
#client.command(pass_context =True)
async def timeout2(ctx, member:discord.User=None, time=None):
#time = humanfriendly.parse_timespan(time)
# tiempo = datetime.timedelta(seconds=time)
user = await client.fetch_user(member)
#await ctx.send (f"{user}")
#await ctx.send (f"{member}")
await user.timeout_for(time)
await ctx.send (f"{user} callate un rato anda {time}")
Best Regards,
Engineer
Update your py-cord library by using pip install -U git+https://github.com/pycord-development/pycord
If works , pls consider accepting answer

How come I can't use message.user.tag?

I'm trying to get the 4-digit tag of the person who used the command !hours, but discord won't recognize user.tag
import discord
from discord import message
from discord.ext import commands
client = commands.Bot(command_prefix = '!')
##########HOURS##########
chung_victor = [21, 10]
##########HOURS##########
# chung_victor
if usertag == 5308:
h = chung_victor[0]
m = chung_victor[1]
await ctx.send(f'> You currently have {h} hours and {m} minutes!')
And when I use !hours, I get the error message
Ignoring exception in command hours:
Traceback (most recent call last):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 85, in wrapped
ret = await coro(*args, **kwargs)
File "main.py", line 36, in hours
usertag = message.user.tag
AttributeError: module 'discord.message' has no attribute 'user'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/bot.py", line 939, in invoke
await ctx.command.invoke(ctx)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 863, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 94, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: module 'discord.message' has no attribute 'user'
Well, as you see to get user name you need to use it as user.name and same goes for the discriminator user.discriminator. You can refer to the code below :
#bot.command()
async def test(ctx, member : discord.Member, *,reason = None) :
user = member.discriminator
await ctx.send(f" User Tag is : {user} ")
In the example above, I set a command test and user must tag someone after a command like:
!test #Victor Chung and ! is a command_prefix.
Thank You :)

Is there a way to call `curio.spawn` from within `asyncio.run`

There is a great library that I want to use from a larger project that I'm working on that uses "standard asyncio". Some of the functionality of the library calls curio.spawn which results in an error when called from "standard asyncio". Is there a way to get this to work?
Example code that reproduces the error:
import curio
import asyncio
async def curio_method():
await curio.sleep(1)
async def asyncio_method():
task = await curio.spawn(curio_method())
await task
asyncio.run(asyncio_method())
Result:
Traceback (most recent call last):
File "/tmp/curio_test.py", line 12, in <module>
asyncio.run(asyncio_method())
File "/usr/lib/python3.9/asyncio/runners.py", line 44, in run
return loop.run_until_complete(main)
File "/usr/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
return future.result()
File "/tmp/curio_test.py", line 8, in asyncio_method
task = await curio.spawn(curio_method())
File "/home/garyvdm/dev/image_builder/bpmagent/ve/lib/python3.9/site-packages/curio/task.py", line 613, in spawn
task = await _spawn(coro)
File "/home/garyvdm/dev/image_builder/bpmagent/ve/lib/python3.9/site-packages/curio/traps.py", line 83, in _spawn
return await _kernel_trap('trap_spawn', coro)
File "/home/garyvdm/dev/image_builder/bpmagent/ve/lib/python3.9/site-packages/curio/traps.py", line 32, in _kernel_trap
result = yield request
RuntimeError: Task got bad yield: ('trap_spawn', <coroutine object curio_method at 0x7fc1b62eeec0>)
sys:1: RuntimeWarning: coroutine 'curio_method' was never awaited
Instead of asyncio.run, you can use curio.run.
But, if you need to use asyncio.run, you can put your curio.run inside your asyncio.run logic. Anyway, I think that is not the idea.

Problem with *.shutdown* command on discord.py

I am currently looking to fix this code. I am trying to make a .shutdown command, which basically logs out of the bot and takes the bot down. I have made a code, but it seems like it is not working. Here is my code. Help is very appreciated ;p
#client.command()
async def shutdown(ctx, *, reason):
if ctx.message.author.id(581457749724889102):
ctx.send('Bot is shutting down... ;(')
logs_channel = client.get_channel(825005282535014420)
logs_channel.send(f"Bot is being shutdown for: {reason}")
exit()
else:
ctx.send("I'm sorry, only officer grr#6609 can do that."
Thanks early for the help!
edit:
here is my error
Ignoring exception in on_command_error
Traceback (most recent call last):
File "C:\Users\USER\AppData\Local\Programs\Python\Python39-32\lib\site-packages\discord\ext\commands\core.py", line 85, in wrapped
ret = await coro(*args, **kwargs)
File "c:\Users\USER\Desktop\discord bot folder\Nuova cartella\connor.py", line 173, in shutdown
if ctx.message.author.id(581457749724889102):
TypeError: 'int' object is not callable
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\USER\AppData\Local\Programs\Python\Python39-32\lib\site-packages\discord\client.py", line 343, in _run_event
await coro(*args, **kwargs)
File "c:\Users\USER\Desktop\discord bot folder\Nuova cartella\connor.py", line 82, in on_command_error
raise error
File "C:\Users\USER\AppData\Local\Programs\Python\Python39-32\lib\site-packages\discord\ext\commands\bot.py", line 902, in invoke
await ctx.command.invoke(ctx)
File "C:\Users\USER\AppData\Local\Programs\Python\Python39-32\lib\site-packages\discord\ext\commands\core.py", line 864, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "C:\Users\USER\AppData\Local\Programs\Python\Python39-32\lib\site-packages\discord\ext\commands\core.py", line 94, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: 'int' object is not callable
Please always consider to await your functions. You also have some formation and comprehension errors in the code, maybe take another look at the docs
You can check whether the user executing the command is the owner of the bot. If he is not, there is of course an error message.
Have a look at the following code:
#client.command()
#commands.is_owner() # Checks if the bot owner exectued the command
async def shutdown(ctx):
await ctx.send("Logging out.")
await client.logout() # Logging out
#shutdown.error
async def shutdown_error(ctx, error):
if isinstance(error, commands.NotOwner):
await ctx.send("You are not the owner of the bot.") # Error message
What did we do?
awaited most of the functions.
Built in a check to check if the owner executed the command.
Built in an error handler which will give out a message if a non-owner tries to shutdown the bot.

This code for changing roles doesn't work

I got this code to change a user's role, but it won't work.
#client.command(pass_context=True)
async def ruleBreak(ctx):
member = ctx.message.author
role = discord.utils.get(member.server.roles, name="RuleBreakers")
await client.add_roles(member, role)
But it's causing this error
Ignoring exception in command ruleBreak:
Traceback (most recent call last):
File "C:\Users\unkno\AppData\Local\Programs\Python\Python38\lib\site-packages\discord\ext\commands\core.py", line 85, in wrapped
ret = await coro(*args, **kwargs)
File "c:/Users/unkno/Desktop/Code_Tests/Python/discord_bot/WIP/bot2.py", line 19, in ruleBreak
role = discord.utils.get(member.server.roles, name="RuleBreakers")
AttributeError: 'Member' object has no attribute 'server'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\unkno\AppData\Local\Programs\Python\Python38\lib\site-packages\discord\ext\commands\bot.py", line 903, in invoke
await ctx.command.invoke(ctx)
File "C:\Users\unkno\AppData\Local\Programs\Python\Python38\lib\site-packages\discord\ext\commands\core.py", line 855, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "C:\Users\unkno\AppData\Local\Programs\Python\Python38\lib\site-packages\discord\ext\commands\core.py", line 94, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'Member' object has no attribute 'server'
What do I do, why is this happening, and where do I change it?
Thanks in advance!
You don't need to pass context as it's done for you in the rewrite branch.
#client.command()
async def ruleBreak(ctx):
member = ctx.message.author
role = discord.utils.get(member.guild.roles, name="RuleBreakers")
await discord.Member.add_roles(member, role)
EDIT: The main issue here was that Client.add_roles changed to Member.add_roles() in the rewrite version. Migrating to v1.0

Resources