python异步编程

python用asyncio 模块实现异步编程,该模块最大特点就是,只存在一个线程

由于只有一个线程,就不可能多个任务同时运行。asyncio 是"多任务合作"模式(cooperative multitasking),允许异步任务交出执行权给其他任务,等到其他任务完成,再收回执行权继续往下执行

asyncio 模块在单线程上启动一个事件循环(event loop),时刻监听新进入循环的事件,加以处理,并不断重复这个过程,直到异步任务结束。

什么是事件循环?

单线程就意味着所有的任务需要在单线程上排队执行,也就是前一个任务没有执行完成,后一个任务就没有办法执行。在CPU密集型的任务之中,这样其实还行,但是如果我们的任务都是IO密集型的呢?也就是我们大部分的任务都是在等待网络的数据返回,等待磁盘文件的数据,这就会造成CPU一直在等待这些任务的完成再去执行下一个任务。

有没有什么办法能够让单线程的任务执行不这么笨呢?其实我们可以将这些需要等待IO设备的任务挂在一边嘛!这时候,如果我们的任务都是需要等待的任务,那么单线程在执行时遇到一个就把它挂起来,这里可以通过一个数据结构(例如队列)将这些处于执行等待状态的任务放进去,为什么是执行等待状态呢?因为它们正在执行但是又不得不等待例如网络数据的返回等等。直到将所有的任务都放进去之后,单线程就可以开始它的接连不断的表演了:有没有任务完成的小伙伴呀!快来我这里执行!

此时如果有某个任务完成了,它会得到结果,于是发出一个信号:我完成了。那边还在循环追问的单线程终于得到了答复,就会去看看这个任务有没有绑定什么回调函数呀?如果绑定了回调函数就进去把回调函数给执行了,如果没有,就将它所在的任务恢复执行,并将结果返回。


import asyncio
import time

async def get_html(url, name):
    print("%s get %s html start" % (name, url))
    await asyncio.sleep(2)
    print("%s get %s html end" % (name, url))


if __name__ == '__main__':
    start=time.time()
    loop = asyncio.get_event_loop()
    # 创建两个协程
    tasks = [
        get_html("http://www.baidu.com", "A"),
        get_html("http://www.souhu.com", "B"),
    ]
    # 启动事件循环并将协程放进去执行
    loop.run_until_complete(asyncio.wait(tasks))
    end=time.time()
    print(end-start)

运行结果:

B get http://www.souhu.com html start
A get http://www.baidu.com html start
B get http://www.souhu.com html end
A get http://www.baidu.com html end
2.0019772052764893
posted @ 2019-12-12 01:09  腹肌猿  阅读(311)  评论(0编辑  收藏  举报