我正在使用discord.py重写编写一个discord bot,我想在某个时间每天运行一个函数 . 我根本没有异步功能的经验,我无法弄清楚如何在不使用“await”的情况下运行它 . 这只是我的代码的一部分,这就是为什么有些东西可能没有被定义的原因 .
async def send_channel():
try:
await active_channel.send('daily text here')
except Exception:
active_channel_id = None
active_channel = None
async def timer():
while True:
schedule.run_pending()
await asyncio.sleep(3)
schedule.every().day.at("21:57").do(await send_channel())
@bot.event
async def on_ready():
print("Logged in as")
print(bot.user.name)
print(bot.user.id)
print("------")
bot.loop.create_task(timer())
使用 schedule.every().day.at("00:00").do()
函数,当我将 await send_channel()
放在 .do()
的参数中时出现此错误:
self.job_func = functools.partial(job_func,* args,** kwargs)TypeError:第一个参数必须是可调用的
但是当我不使用await时,我只有 send_channel()
作为参数,我得到这个错误:
RuntimeWarning:从未等待过coroutine'send_channel'
我不是非常擅长编程,所以如果有人可以尝试为我愚蠢,那将是非常棒的 .
谢谢
1 回答
你're doing doesn'工作是因为
do
接受一个函数(或另一个可调用的函数),但你试图await
或调用一个函数,然后将结果传递给它 .await send_channel()
阻塞,直到发送完成,然后给你None
,这不是一个函数 .send_channel()
返回一个你可以稍后等待做一些工作的协程,这也不是一个函数 .如果你传递它只是
send_channel
,那么,这是一个函数,但它是一个ascynio
协程函数,schedule
将不知道如何运行 .此外,不是试图将
schedule
集成到asyncio
事件循环中,而是想出如何将异步作业包装为schedule
任务,反之亦然,等等,将schedule
给自己的线程要容易得多 .There's a FAQ entry on this:
基本思路很简单 . 将
timer
函数更改为:在程序开始之前,甚至在开始
asyncio
事件循环之前执行此操作 .在退出时,停止调度程序线程:
现在,要添加任务,它不会在您的顶级代码中,或在异步协程中,或在
scheduler
任务中,您只需添加如下:现在,回到你的第一个问题 . 您要运行的任务是't a normal function, it'是一个
asyncio
协程,它必须作为主事件循环的一部分在主线程上运行 .但这正是call_soon_threadsafe的用途 . 你想叫的是:
要让
scheduler
运行它,你只需将bot.loop.call_soon_threadsafe
作为函数传递,并将send_channel
作为参数传递 .所以,把它们放在一起: