前言
在了解了Python并发编程的多线程和多进程之后,我们来了解一下基于asyncio的异步IO编程 => 协程

协程
协程(Coroutine)又称微线程、纤程,协程不是进程或线程,其执行过程类似于 Python 函数调用,Python 的 asyncio 模块实现的异步IO编程框架中,协程是对使用 async 关键字定义的异步函数的调用
一个进程包含多个线程,类似于一个人体组织有多种细胞在工作,同样,一个程序可以包含多个协程。多个线程相对独立,线程的切换受系统控制。同样,多个协程也相对独立,但是其切换由程序自己控制
那协程有什么优势呢?
- 执行效率极高,因为子程序切换(函数)不是线程切换,由程序自身控制,没有切换线程的开销。所以与多线程相比,线程的数量越多,协程性能的优势越明显
- 不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在控制共享资源时也不需要加锁,因此执行效率高很多
Python3.x协程
Python3.x还提供了如下方式实现协程:asyncio + yield from (python3.4+) asyncio + async/await (python3.5+)
Python3.4以后引入了asyncio模块,可以很好的支持协程
asyncio
evnt_loop: 事件循环,相当于一个无限循环,我们可以把一些函数注册到这个事件循环上,当满足条件发生的时候,就会调用对应的处理方法
coroutine: 中文翻译叫协程,在 Python 中常指代为协程对象类型,我们可以将协程对象注册到时间循环中,它会被事件循环调用。我们可以使用 async 关键字来定义一个方法,这个方法在调用时不会立即被执行,而是返回一个协程对象
task: 任务,它是对协程对象的进一步封装,包含了任务的各个状态
future: 代表将来执行或没有执行的任务的结果,实际上和 task 没有本质区别
async
定义异步函数
async def async_function():
print('Number:', 1)
return 1
print(async_function())
输出:
返回一个协程对象
<coroutine object async_function at 0x10a4b0f10>
复制
调用send方法激活
print(async_function().send(None))
复制
异步函数
async def async_function():
print('Number:', 1)
r = requests.get('http://www.baidu.com')
return r
coroutine = async_function()
loop = asyncio.get_event_loop()
t = loop.run_until_complete(coroutine)
print(t)
print('After calling loop')
复制
异步函数task
coroutine = async_function()
loop = asyncio.get_event_loop()
task = loop.create_task(coroutine)
print('Task:', task)
loop.run_until_complete(task)
print('Task:', task)
print('After calling loop')
输出: coroutine 对象多了运行状态,比如 running、finished 等
Task: <Task pending coro=<async_function() running at async_t.py:104>>
Number: 1
Task: <Task finished coro=<async_function() done, defined at async_t.py:104> result=<Response [200]>>
After calling loop
复制
异步函数ensure_future
task = asyncio.ensure_future(coroutine)
print('Task:', task)
loop = asyncio.get_event_loop()
loop.run_until_complete(task)
print('Task:', task)
print('After calling loop')
复制
异步函数绑定回调
async def async_function():
print('Number:', 1)
r = requests.get('http://www.baidu.com')
return r
def callback(task):
print('Status:', task.result())
task = asyncio.ensure_future(coroutine)
task.add_done_callback(callback)
print('Task:', task)
loop = asyncio.get_event_loop()
loop.run_until_complete(task)
print('Task:', task)
复制
异步函数网络并发执行
import requests_async as requests
async def post_requests():
print("Hello world!")
async with requests.Session() as session:
print("create Session statr")
response = await session.get('https://example.org')
print("create Session over")
print(response.status_code)
# print(response.text)
tasks = [post_requests() for host in ['www.sina.com.cn', 'www.sohu.com', 'www.163.com']]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
print('Task:', tasks)
复制
异步函数网络请求
async def get(url):
return requests.get(url)
async def request():
url = 'http://127.0.0.1:5000/api'
print('Waiting for', url)
response = await get(url)
print('Get response from', url, 'Result:', response.text)
tasks = [asyncio.ensure_future(request()) for _ in range(5)]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
复制
多任务异步
import asyncio
import requests
async def request():
url = 'https://www.baidu.com'
status = requests.get(url)
return status
tasks = [asyncio.ensure_future(request()) for _ in range(5)]
print('Tasks:', tasks)
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
for task in tasks:
print('Task Result:', task.result())
复制
aiohttp异步请求
async def aiohttp_get():
url = 'http://127.0.0.1:5000/api'
print('Waiting for', url)
session = aiohttp.ClientSession()
response = await session.get(url)
result = await response.text()
print('Get response from', url)
session.close()
return result
tasks = [asyncio.ensure_future(aiohttp_get()) for _ in range(5)]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
复制
结尾
上面就是python协程的一些简单体验,后续会结合一些协程实战项目,分享更多使的技巧~