【问题标题】:Can I run a message listener alongside an asynchronous looped task?我可以在异步循环任务旁边运行消息侦听器吗?
【发布时间】:2020-12-01 12:54:04
【问题描述】:

我正在使用 discord.py 创建一个机器人,它会定期在 Anilist 上查找用户更新。此任务使用 discord.Client.loop.create_task(task) 运行,并且按预期工作。但是,当我尝试在此任务旁边使用消息侦听器时,机器人没有响应。我之前测试过这段代码 sn-p 并且它可以工作,但除了任务之外它不起作用。

我查看了 discord.py 文档和 asyncio.AbstractEventLoop 上的 create_task 文档,但没有关于同时运行消息侦听器和 AbstractEventLoop 的信息。

client = discord.Client()

#message listener
@client.event
async def on_message(message):
    if message == ".help":
        message.channel.send("test")

#background task
@client.event
@client.event
async def my_background_task():
    await client.wait_until_ready()
    channel = client.get_channel(458644594905710595)
    while not client.is_closed():
        curr_time = int(time.time()-2)
        variables_pat = {
            'userId': 121769,
            'createdAt_greater': curr_time
        }

        variables_hani = {
            'userId': 320308,
            'createdAt_greater': curr_time

        }

        variables_phil = {
            'userId': 163795,
            'createdAt_greater': curr_time
        }

        variables_alan = {
            'userId': 121839,
            'createdAt_greater': curr_time
        }

        variables_ben = {
            'userId': 122953,
            'createdAt_greater': curr_time
        }

        variables_zen = {
            'userId': 382311,
            'createdAt_greater': curr_time
        }

        variables_me = {
            'userId': 323865,
            'createdAt_greater': curr_time
        }

        variables_min = {
            'userId': 169966,
            'createdAt_greater': curr_time
        }
        arr_vars = [variables_alan, variables_ben, variables_hani, variables_pat, variables_phil, variables_zen,
                    variables_me, variables_min]
        for variables in arr_vars:
            response = requests.post(url, json={'query': query, 'variables': variables})
            my_json = json.loads(response.content)
            if my_json["data"] is not None and my_json["data"]["Activity"] is not None:
                activity = my_json["data"]["Activity"]
                print(activity)
                if activity["progress"] is not None:
                    result_string = activity["user"]["name"] + " " + activity["status"] + " " + activity["progress"] + " of " + activity["media"]["title"]["romaji"]
                    result_embed = discord.Embed(
                        title="New Anilist Post",
                        color=discord.Color(0x039AFF),
                        description=result_string
                    )
                    await channel.send(embed=result_embed)
                else:
                    result_string = activity["user"]["name"] + " " + activity["status"] + " " + activity["media"]["title"]["romaji"]
                    result_embed = discord.Embed(
                        title="New Anilist Post",
                        color=discord.Color(0x039AFF),
                        description=result_string
                    )
                    await channel.send(embed=result_embed)

client.loop.create_task(my_background_task())
client.run(os.getenv("DISCORD_TOKEN"))

【问题讨论】:

  • 如果它完全没有响应,可能是因为您的后台任务没有足够异步(有阻塞调用阻碍)..因为您省略了该代码,所以很难准确判断.
  • 我添加了(非常草率的)代码
  • 使用 aiohhtp 而不是 requests 以便您的 http 调用是异步的。它已经作为discord.py 的依赖项安装。你可以在这里看到一个例子:discordpy.readthedocs.io/en/latest/…
  • 是的。 requests.post 处于阻塞状态,只有有条件地到达 await,因此在两者之间没有空间处理其他任务。你至少需要一个await asyncio.sleep(N) 才能有其他东西进入的机会。

标签: python async-await discord.py


【解决方案1】:

你可以做你想做的事,但是你应该使用命令框架。这是一个例子

import discord
from discord.ext import commands, tasks

bot = commands.Bot(command_prefix='-')

bot.remove_command('help') # Remove the built-in help command since we have our own

@bot.event
async def on_ready():
    # Once the bot has connected and is ready to go
    bot.my_current_task = my_task.start()

@tasks.loop(minutes=1) # Run every minute, takes hours, minutes, etc
async def my_task():
    # Put the code to be executed every loop here
    print("The loop hath run")

@my_task.before_loop # Before we start the loop make sure the bot is ready to go
async def before_my_task():
    await bot.wait_until_ready()

# Now the commands framework is nice, no longer do you need to handle commands within on_message
@bot.command()
async def help(ctx):
    await ctx.send("Hello and welcome to my help command")

bot.run("TOKEN HERE")

在此处使用您的代码,然后简单地转换为使用 aiohttp 希望对大家有帮助,有什么问题可以追问!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-09
    • 1970-01-01
    • 2020-07-30
    • 1970-01-01
    • 2013-03-01
    • 1970-01-01
    • 2014-07-19
    相关资源
    最近更新 更多