python的sched模块可​​以在任务执行期间不阻塞地运行异步任务吗?

Posted

技术标签:

【中文标题】python的sched模块可​​以在任务执行期间不阻塞地运行异步任务吗?【英文标题】:Can python's sched module run asynchronous tasks without blocking during a task execution? 【发布时间】:2019-11-18 21:35:27 【问题描述】:

我有一个 Module 类,带有一个 invoke() 方法,它可能会执行一些 IO 绑定/等待。

我使用sched 以不同的时间间隔运行所述类的多个实例,这种方式可能会使长时间运行的调用与另一个任务重叠。

sched 模块能否生成不同的任务并以非阻塞方式处理它们,如果不能,哪个模块可以为多个重复的并发任务完成这项工作

我查看了sched,但找不到任何明确的答案。 我还查看了asyncio,这提示我有两个似乎不符合我需求的答案,分别是while True (which seems cumbersome) 和Tasks (which doesn't appear to allow to run multiple methods concurrently)。

【问题讨论】:

Asyncio 模块就是您所需要的。 根据我能找到的情况,我猜的差不多了,但是我应该遵循哪种结构来正确地制作经常性的并发计划任务? 【参考方案1】:

研究下面的代码,Luciano Ramalho 的 Fluent Python 第 18 章是关于 asyncio 模块的优秀资源。另外,永远不要忘记https://docs.python.org/3/library/asyncio.html

上的文档本身
#!/usr/bin/env python3

# spinner_asyncio.py

# credits: Example by Luciano Ramalho inspired by
# Michele Simionato's multiprocessing example in the python-list:
# https://mail.python.org/pipermail/python-list/2009-February/538048.html

import asyncio
import itertools
import sys


@asyncio.coroutine  # <1>
def spin(msg):  
    write, flush = sys.stdout.write, sys.stdout.flush
    for char in itertools.cycle('|/-\\'):
        status = char + ' ' + msg
        write(status)
        flush()
        write('\x08' * len(status))
        try:
            yield from asyncio.sleep(.1)  # <3>
        except asyncio.CancelledError:  # <4>
            break
    write(' ' * len(status) + '\x08' * len(status))


@asyncio.coroutine
def slow_function():  # <5>
    # pretend waiting a long time for I/O, Non-blocking call!
    yield from asyncio.sleep(3)  # <6>
    return 42


@asyncio.coroutine
def supervisor():  # <7>
    spinner = asyncio.async(spin('thinking!'))  # <8>
    print('spinner object:', spinner)  # <9>
    result = yield from slow_function()  # <10>
    spinner.cancel()  # <11>
    return result


def main():
    loop = asyncio.get_event_loop()  # <12>
    result = loop.run_until_complete(supervisor())  # <13>
    loop.close()
    print('Answer:', result)


if __name__ == '__main__':
    main()

1: 用于 asyncio 的协程应该用 @asyn 修饰 cio.coroutine。这不是强制性的,但强烈建议这样做。

3:使用 asyncio.sleep(.1) 中的 yield 而不是 time.sleep(.1) 来休眠 不阻塞事件循环。

4:如果在 spin 唤醒后引发 asyncio.CancelledError,那是因为 已请求取消,因此退出循环。

5:slow_function 是协程,使用yield from 让事件循环 在这个协程假装通过睡眠进行 I/O 时继续进行。

6: yield from asyncio.sleep(3) 表达式处理控制流到 主循环,它将在睡眠延迟后恢复这个协程。

7: supervisor也是一个协程,所以它可以通过yield驱动slow_function 来自。

8: asyncio.async(...) 调度自旋协程运行,将其包装在一个任务中 对象,立即返回

9:显示任务对象。输出看起来像 Task pending coro= spin() 在 spinner_asyncio.py:12 运行。

10: 驱动 slow_function()。完成后,获取返回值。 同时,事件循环将继续运行,因为 slow_function 最终使用来自 asyncio.sleep(3) 的 yield 将控制权交还给 main 循环。

11:可以取消一个Task对象;这会在产量处引发 asyncio.CancelledError 协程当前暂停的行。协程可能会捕获 异常和延迟甚至拒绝取消。

12:获取事件循环的引用。

13:驱动supervisor协程完成;协程的返回值 是这个调用的返回值。

【讨论】:

以上是关于python的sched模块可​​以在任务执行期间不阻塞地运行异步任务吗?的主要内容,如果未能解决你的问题,请参考以下文章

python定时任务-sched模块

python定时任务-sched模块

python的sched模块--延时调度

使用sched库完成周期定时任务

sched 模块中巨好用的轻量级定时任务神器scheduler!

schedule任务调度及其用法(多线程并发)