【发布时间】:2018-12-19 21:09:06
【问题描述】:
我的程序应该 24/7 运行,我希望能够在某个时间/日期运行一些任务。
我已经尝试过使用aiocron,但它只支持调度函数(不支持协程),我读过这不是一个非常好的库。 我的程序是这样构建的,即使不是所有我想要安排的任务都内置在协程中。
是否有任何其他库允许进行此类任务调度?
如果不是,是否有任何方式扭曲协程以使其运行正常功能?
【问题讨论】:
标签: python scheduled-tasks python-asyncio
我的程序应该 24/7 运行,我希望能够在某个时间/日期运行一些任务。
我已经尝试过使用aiocron,但它只支持调度函数(不支持协程),我读过这不是一个非常好的库。 我的程序是这样构建的,即使不是所有我想要安排的任务都内置在协程中。
是否有任何其他库允许进行此类任务调度?
如果不是,是否有任何方式扭曲协程以使其运行正常功能?
【问题讨论】:
标签: python scheduled-tasks python-asyncio
我已经尝试过使用 aiocron,但它只支持调度功能(不支持协程)
根据您提供的link 中的示例,情况似乎并非如此。 @asyncio.coroutine修饰的函数相当于async def定义的协程,可以互换使用。
但是,如果您想避免使用 aiocron,可以直接使用 asyncio.sleep 将协程的运行推迟到任意时间点。例如:
import asyncio, datetime
async def wait_until(dt):
# sleep until the specified datetime
now = datetime.datetime.now()
await asyncio.sleep((dt - now).total_seconds())
async def run_at(dt, coro):
await wait_until(dt)
return await coro
示例用法:
async def hello():
print('hello')
loop = asyncio.get_event_loop()
# print hello ten years after this answer was written
loop.create_task(run_at(datetime.datetime(2028, 7, 11, 23, 36),
hello()))
loop.run_forever()
注意:3.8 之前的 Python 版本不支持超过 24 天的睡眠间隔,因此 wait_until 必须解决这个限制。这个答案的原始版本是这样定义的:
async def wait_until(dt):
# sleep until the specified datetime
while True:
now = datetime.datetime.now()
remaining = (dt - now).total_seconds()
if remaining < 86400:
break
# pre-3.7.1 asyncio doesn't like long sleeps, so don't sleep
# for more than one day at a time
await asyncio.sleep(86400)
await asyncio.sleep(remaining)
在 Python 3.8 中的限制是 removed,并且该修复已向后移植到 3.6.7 和 3.7.1。
【讨论】:
loop.call_at 接受相对于loop.time() 返回的时间的时间参考,因此您仍然需要计算并且不能只给它一个例如Unix 时间戳。第二个问题是call_at 接受一个函数,而不是协程,所以你仍然需要一个调用create_task 的蹦床。使用call_at(和call_later 和call_soon)你不能轻易地获得协程的返回值,就像在编辑的答案中所做的那样。