import asyncio
from datetime import datetime
class Tasks:
def __init__(self):
self.tasks = []
def loop_run(self, func, interval=1, *args, **kwargs):
self.tasks.append(asyncio.ensure_future(self._loop_run(func, interval, *args, **kwargs)))
async def _loop_run(self, func, interval, *args, **kwargs):
while True:
t = datetime.now()
await func(*args, **kwargs)
elapsed = (datetime.now() - t).total_seconds()
await asyncio.sleep(interval - elapsed)
def run(self, func, delay=0):
if delay > 0:
asyncio.ensure_future(self._delay_run(func, delay))
else:
asyncio.ensure_future(func())
async def _delay_run(self, func, delay):
await asyncio.sleep(delay)
await func()
def run_until_complete(self):
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(self.tasks))
To use it:
tasks = Tasks()
# Register loop task
tasks.loop_run(my_func, 60)
# Register delayed task
tasks.run(my_func2, delay=5)
tasks.run_until_complete()
这段代码定义了一个名为 Tasks 的类,它使用 asyncio 在 Python 中帮助调度和异步运行任务。以下是代码的解释:
-
Tasks 类的 init 方法初始化了一个空列表 tasks ,用于存储已调度的任务。
-
loop_run 方法按照指定的时间间隔循环调度一个任务。它接受一个函数( func )作为参数,还可以指定一个可选的时间间隔(默认为 1 秒),以及其他任意的位置参数和关键字参数( *args 和 **kwargs )。该方法使用 asyncio.ensure_future 在事件循环中调度任务。
-
_loop_run 方法是一个内部方法,用于在循环中运行任务。它执行提供的函数( func )以及传入的参数,并等待其完成。然后计算经过的时间,并在剩余的时间间隔内进行休眠,然后再次运行任务。
-
run 方法调度一个任务仅运行一次。它接受一个函数( func )作为参数,还可以指定一个可选的延迟时间(默认为 0 秒)。如果指定了延迟时间,它会使用 _delay_run 方法在指定的延迟后执行函数。否则,它直接使用 asyncio.ensure_future 调度函数。
-
_delay_run 方法是一个内部方法,在指定的延迟时间后执行提供的函数( func )。
-
run_until_complete 方法启动事件循环,并运行所有已调度的任务,直到它们完成。它使用 asyncio.get_event_loop 获取事件循环,并使用 loop.run_until_complete 运行任务。
要使用这段代码,您可以创建一个 Tasks 类的实例,并使用 loop_run 或 run 方法调度您的任务。最后,调用 run_until_complete 方法启动事件循环并运行已调度的任务。
这里是使用Python实现该Tasks模块的一种方式:
1. 导入需要的asyncio模块和datetime。
2. 创建Tasks类,包含任务列表tasks。
3. loop_run方法用来注册循环执行的任务:
- 接收一个异步回调函数func
- 执行间隔时间interval,默认为1秒
- 接受位置参数和关键字参数*args,**kwargs
4. _loop_run内部会不断调用func,并控制每次调用的间隔时间。
5. run方法用来注册单次执行的任务:
- 如果设定delay>0,则延时执行func
- delay=0则立即执行func
6. _delay_run内部使用asyncio.sleep实现延时等待。
7. run_until_complete会运行事件循环,直到所有任务完成。
8. 使用时,先注册任务,然后调用run_until_complete即可。
这个模块利用了asyncio的coroutine和事件循环机制,可以方便地注册和调度不同类型的任务。
通过asyncio避免了自行管理线程的复杂度,使得任务调度以异步的流程编写,但是执行仍然是并发的。