如何在python中触发异步非阻塞调度任务或事件?
我写了一个我的问题的示例代码。输入消息被分成固定块,并使用有意的随机延迟进行混合。但是,sleep()
正在阻止并且不会运行下一个任务。这是可能的单线程还是我不得不求助于多线程?如何在python中触发异步非阻塞调度任务或事件?
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
并使其非阻塞,并且还具有其自身的非阻塞睡眠。它也可以修补整个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密集型任务不能在greenlets运行,因为它们会阻止事件循环和所有其他greenlets。
只要在greenlet中运行的是I/O绑定,就像在套接字或生成器中传递消息一样,其他greenlets等,greenlet也是适用的。对于CPU绑定的任务,请使用本机线程或多个进程。
还有其他的选择,比如asyncio
(仅Py3)。 Gevent与Py2和3兼容,并且具有非常高的性能,并由本机代码扩展支持。
谢谢,这很有趣。通过CPU绑定,你的意思是,如果delay_message执行繁重的操作?或者你可以给我一个例子,你的意思是这样的 – Anderson
CPU绑定任务将是在CPU上执行代码时被阻塞的任何东西。例如音频/视频编码和解码,图像处理等,基本上涉及在CPU上运行的代码。 I/O绑定任务将通过网络读取/写入流,网络请求处理,磁盘I/O等。网络也可以由线程来处理,但这意味着很多CPU开销(CPU使用率增加,最大并发度降低)对于事实上并未受CPU限制的事情。为此,合作多任务即异步I/O更适合。 – danny
这是有道理的感谢。 Gevent没有'usleep()或nanosleep()'高度的准确性。有没有办法处理这与当前的方法?或者你能否建议另一种方式,我可以研究 – Anderson
查看['asyncio'](https://docs.python.org/3/library/asyncio.html)。如果它真的只是你需要的非阻塞睡眠,那可能会有所帮助。 –