如何异步非阻止在python中触发的调度任务或事件?

时间:2017-06-16 15:07:02

标签: python scheduled-tasks scheduler

我写了一个问题的示例代码。输入消息被分成固定的块并使用有意的随机延迟进行混合。但是,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()

1 个答案:

答案 0 :(得分:1)

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

可以使用gevent等库来使其无阻塞。 Gevent还可以修补time.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绑定,比如在套接字或生成器中传递消息,其他greenlet等,greenlets是合适的。对于CPU绑定任务,请使用本机线程或多个进程。

还有其他选择,例如asyncio(仅限Py3)。 Gevent与Py2和3兼容,具有非常高的性能,以本机代码扩展为后盾。