python - 如何在Python中异步非阻塞调度任务或事件触发?

标签 python scheduled-tasks scheduler

我已经编写了我的问题的示例代码。输入消息被分成固定的 block ,并使用有意的随机延迟进行混合。但是,sleep() 处于阻塞状态,不会运行下一个任务。这在单线程上可行还是必须诉诸多线程?

from random import randint
from time import sleep

def delay_message(split_message, delay):
    #sleep(delay) #this blocks
    print("Shuffled message: {} and time: {}". format(split_message, delay)) 

def main():
    message = raw_input('Input: ')

    #padding
    difference = len(message) % 5
    message=message.ljust(len(message)+5-difference, "0")

    for i in range(0, len(message), 5):
        delay = randint(0, 5)
        split_message = message[i:i+5]
        delay_message(split_message, delay)

if __name__ == "__main__":
    main()

最佳答案

sleep 确实会阻塞其正在运行的线程。

可以通过使用像gevent这样的库使其成为非阻塞的。 。 Gevent 还可以修补 time.sleep 并使其成为非阻塞,并且也有自己的非阻塞 sleep 。它还可以修补整个 python 标准库,使其成为非阻塞 - 套接字、时间、线程等,请参阅 documentation .

上面的例子可以与 gevent 协同并发,如下所示:

from random import randint
from gevent import sleep, spawn, joinall

def delay_message(split_message, delay):
    # Gevent's sleep yields the event loop for
    # duration of delay rather than blocking the running thread
    sleep(delay)
    print("Shuffled message: {} and time: {}". format(split_message, delay)) 

def main():
    message = raw_input('Input: ')

    #padding
    difference = len(message) % 5
    message=message.ljust(len(message)+5-difference, "0")

    greenlets = []
    # This will create len(message)/5 number of greenlets,
    # which corresponds to the concurrency level.
    # Greenlets all run under one thread so there is no CPU
    # overhead here.
    for i in range(0, len(message), 5):
        delay = randint(0, 5)
        split_message = message[i:i+5]
        greenlets.append(spawn(delay_message, split_message, delay))
    # Wait for all greenlets to complete, raise any exceptions
    joinall(greenlets, raise_error=True)

if __name__ == "__main__":
    main()

限制是 CPU 密集型任务不能在 greenlet 中运行,因为它们会阻塞事件循环和所有其他 greenlet。

只要 greenlet 中运行的内容是 I/O 绑定(bind)的,例如在套接字或生成器、其他 greenlet 等中传递消息,greenlet 都是合适的。对于 CPU 密集型任务,请使用 native 线程或多进程。

还有其他替代方案,例如 asyncio(仅限 Py3)。 Gevent 与 Py2 和 3 兼容,并且具有非常高的性能,并由 native 代码扩展支持。

关于python - 如何在Python中异步非阻塞调度任务或事件触发?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44592528/

相关文章:

kotlin - 如何在 kotlin 中安排重复任务?

Cron 作业每 x 周和特定日期运行一次

python - 无法使用python在selenium中上传图像

python - 计算列表中的对数,不考虑顺序

python - 为什么在 `dir()` 输出中省略了一些功能?

java - 有没有办法在spring boot的main方法中调用@Scheduled注解

kubernetes - K8s调度守护程序集

python - 传递给函数的未知类型的约束

python-3.x - Python 多进程调度

基于相对优先级的作业调度算法