异步IO:当代码需要执行一个耗时的IO操作时,它只发出IO指令,并不等待IO结果,然后就去执行其他代码
同步IO:遇到IO操作,如读写文件、发送网络数据时,需要等待IO操作完成
协程
单线程实现并发,在应用程序里控制多个任务的切换+保存状态,有线程切换的开销,使用yield
协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的
https://www.liaoxuefeng.com/wiki/1016959663602400/1017959540289152
使用的原因:不能无限增加线程、解决同步IO
协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行。
def foo(): while True: x = yield print("value:",x) g = foo() # g是一个生成器 next(g) # 程序运行到yield就停住了,等待下一个next g.send(1) # 我们给yield发送值1,然后这个值被赋值给了x,并且打印出来,然后继续下一次循环停在yield处 g.send(2) # 同上 next(g) # 没有给x赋值,执行print语句,打印出None,继续循环停在yield处
asyncio
asyncio的编程模型就是一个消息循环。我们从asyncio模块中直接获取一个EventLoop的引用,然后把需要执行的协程扔到EventLoop中执行,就实现了异步IO。
Python3.4
import asyncio @asyncio.coroutine # 把一个generator标记为coroutine类型,丢到EventLoop执行 def hello(): print("Hello world!") # 异步调用asyncio.sleep(1): r = yield from asyncio.sleep(1) # 不会等待直接中断并执行下一个消息循环,返回时执行下一语句 print("Hello again!") # 获取EventLoop: loop = asyncio.get_event_loop() # 执行coroutine tasks = [hello(), hello()] loop.run_until_complete(asyncio.wait(tasks)) loop.close() # 输出 Hello world! (<_MainThread(MainThread, started 140735195337472)>) Hello world! (<_MainThread(MainThread, started 140735195337472)>) (暂停约1秒) Hello again! (<_MainThread(MainThread, started 140735195337472)>) Hello again! (<_MainThread(MainThread, started 140735195337472)>)
python3.5 引入async(@asyncio.coroutine) await(yield from)
async def hello(): print("Hello world!") r = await asyncio.sleep(1) print("Hello again!")
aiohttp则是基于asyncio实现的HTTP框架