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

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.

Related

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 :)

How to await Tasks created inside an endless loop in 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.

How do you get the main "function" of a command in discord.py?

I'm trying to create a command that sends the code of another command in discord.py. For example, if I had a command for rock paper scissors and i ran .code rps, It would send the code for the rps command. Here is my code so far:
import inspect
import discord
from discord.ext.commands import Bot, cooldown, BucketType, CommandOnCooldown
from discord.ext import commands, tasks
#bot.command(hidden=True)
#commands.is_owner()
async def code(ctx, *, command_name):
"""Sends code of a command"""
com = bot.get_command(command_name)
if com is None:
await ctx.reply(f"Bruh that isn't a command", mention_author=False)
elif com:
source = inspect.getsource(com)
try:
await ctx.reply(f"```\n{source}\n```", mention_author=False)
except discord.HTTPException:
await ctx.reply(f"That command's code is too long for me to send lmao", mention_author=False)
print(source)
But there's an error because it can't find the source code of a command type
Ignoring exception in command code:
Traceback (most recent call last):
File "/Users/Bello/PycharmProjects/larry/venv3.8/lib/python3.8/site-packages/discord/ext/commands/core.py", line 85, in wrapped
ret = await coro(*args, **kwargs)
File "/Users/Bello/PycharmProjects/larry/venv3.8/test.py", line 351, in code
source = inspect.getsource(com)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/inspect.py", line 985, in getsource
lines, lnum = getsourcelines(object)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/inspect.py", line 967, in getsourcelines
lines, lnum = findsource(object)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/inspect.py", line 780, in findsource
file = getsourcefile(object)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/inspect.py", line 696, in getsourcefile
filename = getfile(object)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/inspect.py", line 676, in getfile
raise TypeError('module, class, method, function, traceback, frame, or '
TypeError: module, class, method, function, traceback, frame, or code object was expected, got Command
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/Bello/PycharmProjects/larry/venv3.8/lib/python3.8/site-packages/discord/ext/commands/bot.py", line 902, in invoke
await ctx.command.invoke(ctx)
File "/Users/Bello/PycharmProjects/larry/venv3.8/lib/python3.8/site-packages/discord/ext/commands/core.py", line 864, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "/Users/Bello/PycharmProjects/larry/venv3.8/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: TypeError: module, class, method, function, traceback, frame, or code object was expected, got Command
Is there a way to find the source code of a command object or figure out a loophole that lets me do that? Thanks!!
Simply use the callback attribute
func = com.callback
source = inspect.getsource(func)
Reference:
Command.callback

How do i create a Ticket command in discord.py?

Hello so i want to make a discord bot that can create tickets but i am not sure on how do it i am using discord.py and i was wondering if anyone can help? i have tried this.
#bot.command()
async def ticket(ctx):
await create_text_channel(name, *, overwrites=None, reason=None, **options)
But it does not do anything and i get this error.
Traceback (most recent call last):
File "C:\Users\Robin\AppData\Roaming\Python\Python37\site-packages\discord\ext\commands\bot.py", line 903, in invoke
await ctx.command.invoke(ctx)
File "C:\Users\Robin\AppData\Roaming\Python\Python37\site-packages\discord\ext\commands\core.py", line 855, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "C:\Users\Robin\AppData\Roaming\Python\Python37\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: NameError: name 'create_text_channel' is not defined```
There are three mistakes in the code you gave:
create_text_channel() is a discord.Guild class method so it only works with a Guild instance
The name variable isn't defined so you'd have an error.
If you don't need any overwrites or any reason, you don't need to write overwrites=None and reason=None, same goes for *.
In the end, your code would look like this:
#bot.command()
async def ticket(ctx):
await ctx.guild.create_text_channel('Channel Name')
I guess you looked at the documentation and copy pasted the method's title, which is unnecessary, you could have looked at the examples given, eg. channel = await guild.create_text_channel('cool-channel')
If you want to create a hidden channel, there's also this example:
overwrites = {
guild.default_role: discord.PermissionOverwrite(read_messages=False),
guild.me: discord.PermissionOverwrite(read_messages=True)
}
channel = await guild.create_text_channel('secret', overwrites=overwrites)

How to fix 'create_channel BAD REQUEST(status code : 400)' in Discord.py

There was no problem with this code. But one day, suddenly, an error started to appear. Please help me. (I used the translator.) Thanks
I have no idea.. Sorry.
#client.command(pass_context=True)
async def test(ctx):
server = ctx.message.server
name = "NAME"
await client.create_channel(server, "NAME", type=discord.ChannelType.voice)
This is error code.
Traceback (most recent call last):
File "/home/ydepong93/.local/lib/python3.6/site-packages/discord/ext/commands/core.py", line 50, in wrapped
ret = yield from coro(args, **kwargs)
File "feelblue.py", line 5790, in test
await client.create_channel(server, name, type=discord.ChannelType.text)
File "/home/ydepong93/.local/lib/python3.6/site-packages/discord/client.py", line 2163, in create_channel
data = yield from self.http.create_channel(server.id, name, str(type), permission_overwrites=perms)
File "/home/ydepong93/.local/lib/python3.6/site-packages/discord/http.py", line 200, in request
raise HTTPException(r, data)
discord.errors.HTTPException: BAD REQUEST (status code: 400)
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/ydepong93/.local/lib/python3.6/site-packages/discord/ext/commands/bot.py", line 846, in process_commands
yield from command.invoke(ctx)
File "/home/ydepong93/.local/lib/python3.6/site-packages/discord/ext/commands/core.py", line 374, in invoke
yield from injected(ctx.args, **ctx.kwargs)
File "/home/ydepong93/.local/lib/python3.6/site-packages/discord/ext/commands/core.py", line 54, in wrapped
raise CommandInvokeError(e) from e
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: HTTPException: BAD REQUEST (status code: 400)
Have a look here: https://discordpy.readthedocs.io/en/latest/api.html?highlight=create_voice#discord.Guild.create_voice_channel
You must use
await ctx.guild.create_voice_channel(**kwargs)
Instead of your code. Next times better if you give the docs a look before asking here.

Resources