z1115230598

异步协程

  • event_loop:事件循环,相当于一个无限循环,我们可以把一些函数注册到这个事件循环上,当满足某些条件的时候,函数就会被循环执行。程序是按照设定的顺序从头执行到尾,运行的次数也是完全按照设定。当在编写异步程序时,必然其中有部分程序的运行耗时是比较久的,需要先让出当前程序的控制权,让其在背后运行,让另一部分的程序先运行起来。当背后运行的程序完成后,也需要及时通知主程序已经完成任务可以进行下一步操作,但这个过程所需的时间是不确定的,需要主程序不断的监听状态,一旦收到了任务完成的消息,就开始进行下一步。loop就是这个持续不断的监视器。

  • coroutine:中文翻译叫协程,在 Python 中常指代为协程对象类型,我们可以将协程对象注册到事件循环中,它会被事件循环调用。我们可以使用 async 关键字来定义一个方法,这个方法在调用时不会立即被执行,而是返回一个协程对象。

  • task:任务,它是对协程对象的进一步封装,包含了任务的各个状态。

  • future:代表将来执行或还没有执行的任务,实际上和 task 没有本质区别。

  • 另外我们还需要了解 async/await 关键字,它是从 Python 3.5 才出现的,专门用于定义协程。其中,async 定义一个协程,await 用来挂起阻塞方法的执行。

基本使用

#基本使用
import asyncio
async def hello(name):
    print(\'hello to :\',name)
#获取了一个协程对象
c = hello(\'shazi\')

#创建一个事件循环对象
loop = asyncio.get_event_loop()

#将协程对象注册到事件循环中,然后启动事件循环对象
loop.run_until_complete(c)

task的使用

import asyncio
async def hello(name):
    print(\'hello to :\',name)

c = hello(\'shazi\')
loop = asyncio.get_event_loop()
#就协程进行进一步的封装,封装到了task对象中
task = loop.create_task(c)
print(task)
loop.run_until_complete(task)
print(task)
task的使用

 future的使用

#future
import asyncio
async def hello(name):
    print(\'hello to :\',name)

c = hello(\'shazi\')

task = asyncio.ensure_future(c)

loop.run_until_complete(task)

 绑定回调

def callback(task):
    print(\'i am callback:\',task.result())

import asyncio
async def hello(name):
    print(\'hello to :\',name)
    return name

c = hello(\'shazi\')

task = asyncio.ensure_future(c)
#给任务对象绑定一个回调函数
task.add_done_callback(callback)
loop.run_until_complete(task)

多任务异步协程

import asyncio
async def request(url):
    print(\'正在下载:\',url)
    sleep(2) #非异步模块的代码:在此处如果存在非异步操作代码,则会彻底让asyncio失去异步的效果
    print(\'下载成功:\',url)
urls = [
    \'www.baidu.com\',
    \'www.taobao.com\',
    \'www.sogou.com\'
]
start = time.time()
loop = asyncio.get_event_loop()
tasks = [] #任务列表,放置多个任务对象
for url in urls:
    c = request(url)
    task = asyncio.ensure_future(c)
    tasks.append(task)
    
#将多个任务对象对应的列表注册到事件循环中
loop.run_until_complete(asyncio.wait(tasks))
print(\'总耗时:\',time.time()-start)
    
失去异步的情况
import asyncio
async def request(url):
    print(\'正在下载:\',url)
#     sleep(2) #非异步模块的代码:在此处如果存在非异步操作代码,则会彻底让asyncio失去异步的效果
    await asyncio.sleep(2)
    print(\'下载成功:\',url)
urls = [
    \'www.baidu.com\',
    \'www.taobao.com\',
    \'www.sogou.com\'
]
start = time.time()
loop = asyncio.get_event_loop()
tasks = [] #任务列表,放置多个任务对象
for url in urls:
    c = request(url)
    task = asyncio.ensure_future(c)
    tasks.append(task)
    
#将多个任务对象对应的列表注册到事件循环中
loop.run_until_complete(asyncio.wait(tasks))
print(\'总耗时:\',time.time()-start)
异步

requests模块是一个非异步模块

 

import requests
async def get_page(url):
    print(\'正在下载:\',url)
    #之所以没有实现异步操作,原因是因为requests模块是一个非异步的模块
    response = requests.get(url=url)
    print(\'响应数据:\',response.text)
    print(\'下载成功:\',url)
start = time.time()
urls = [
    \'http://127.0.0.1:5000/haha\',
    \'http://127.0.0.1:5000/heihei\',
    \'http://127.0.0.1:5000/xixi\'
]
tasks = []
loop = asyncio.get_event_loop()
for url in urls:
    c = get_page(url)
    task = asyncio.ensure_future(c)
    tasks.append(task)
loop.run_until_complete(asyncio.wait(tasks))
print(\'总耗时:\',time.time()-start)
非异步模块requests

 

支持异步的网络请求的模块:aiohttp

环境安装: pip install aiohttp

 为了更好的显示效果自己搭一个简单的服务器

from flask import Flask
import time

app=Flask(__name__)
@app.route(\'/haha\')
def haha():
    time.sleep(2)
    return \'Hi haha\'

@app.route(\'/heihei\')
def heihei():
    time.sleep(2)
    return \'Hi heihei\'

@app.route(\'/xixi\')
def xixi():
    time.sleep(2)
    return \'Hi xixi\'
if __name__ == \'__main__\':
    app.run(threaded=True)
服务器的简单搭建
import aiohttp
import asyncio

async def get_page(url):
    async with aiohttp.ClientSession() as session:
        async with await session.get(url=url) as response:
            page_text = await response.text() #read()  json()
            print(page_text)
start = time.time()
urls = [
    \'http://127.0.0.1:5000/haha\',
    \'http://127.0.0.1:5000/heihei\',
    \'http://127.0.0.1:5000/xixi\',
    \'http://127.0.0.1:5000/haha\',
    \'http://127.0.0.1:5000/heihei\',
    \'http://127.0.0.1:5000/xixi\',
    \'http://127.0.0.1:5000/haha\',
    \'http://127.0.0.1:5000/heihei\',
    \'http://127.0.0.1:5000/xixi\'
]
tasks = []
loop = asyncio.get_event_loop()
for url in urls:
    c = get_page(url)
    task = asyncio.ensure_future(c)
    tasks.append(task)
loop.run_until_complete(asyncio.wait(tasks))
print(\'总耗时:\',time.time()-start)
异步的网络请求

 

分类:

技术点:

相关文章: