每天特定时间的Discord.py Bot运行功能

问题描述

我正在使用discord.py创建一个discord机器人,我需要每天在特定时间执行某些操作。我看到了这个答案:How to make a loop in discord.py rewrite?,到目前为止我一直在使用它。

当我将机器人托管在heroku免费计划上时,问题就开始了。 Heroku上的服务器每天至少重置一次,这会弄乱计时器,如该帖子中所示。

我还看到了schedule库。问题在于它似乎使用了无限循环。那不会阻止我在24小时内运行其他任何东西吗?除了每24小时发送一次消息外,该机器人还需要始终能够响应命令。

即使服务器重置,如何每天仍在特定时间执行操作?预先谢谢你!

解决方法

您可以编写一个函数,使其在其他线程上定期运行,并检查是否是发送消息的正确时机,例如以下示例:

from datetime import datetime
import threading


def checkTime():
    # This function runs periodically every 1 second
    threading.Timer(1,checkTime).start()

    now = datetime.now()

    current_time = now.strftime("%H:%M:%S")
    print("Current Time =",current_time)

    if(current_time == '02:11:00'):  # check if matches with the desired time
        print('sending message')


checkTime()
,

您是否考虑过使用多线程来运行程序?您可能有一个线程在等待一天中所需的时间,而另一个正在运行程序的其余部分。 以下是一些文档可帮助您入门:documentationIntro to Python Threading

,

heroku免费计划是Linux。因此,cron可以让您在特定时间运行,而/etc/init.d/可以让您在启动时运行。了解您的操作系统是一件好事。

,

我知道我迟到了,但这可能对未来的用户有帮助。
有一个名为 APScheduler 的库可用于通过设置 cron 作业来运行函数(也有其他方法代替 cron。Read more)。

一个小例子如下:

import discord
from discord.ext import commands

from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.cron import CronTrigger

class Scheduler(commands.Cog):
    """Schedule commands."""
    def __init__(self,bot):
        self.bot = bot

        # Initialize session
        self.session = aiohttp.ClientSession()
    
    # Scheduled events
    async def schedule_func(self):

    def schedule(self):
        # Initialize scheduler
        schedule_log = logging.getLogger("apscheduler")
        schedule_log.setLevel(logging.WARNING)

        job_defaults = {
            "coalesce": True,"max_instances": 5,"misfire_grace_time": 15,"replace_existing": True,}

        scheduler = AsyncIOScheduler(job_defaults = job_defaults,logger = schedule_log)

        # Add jobs to scheduler
        scheduler.add_job(self.schedule_func,CronTrigger.from_crontab("0 * * * *")) 
        # Every hour

并在我们的 main.py 文件中添加以下内容(显然是在导入 schedule_jobs.py 文件之后):

# Start scheduled commands
scheduler = schedule_jobs.Scheduler(bot).schedule()
scheduler.start()
,

您可以有一个无限循环并使用asyncio.sleep()函数。这使您可以从脚本中的任何位置处理命令,并且仍然等待时间。这是一个小例子:

import asyncio

while True:
    await asyncio.sleep(60)
    print(1)

@client.command()
async def command(ctx):
    pass

每分钟脚本将打印1,并且只要有人执行该命令就会执行。