侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

python 异步async库的使用说明

Python  /  管理员 发布于 7年前   417

在学习asyncio之前,先理清楚同步/异步的概念:

同步是指完成事务的逻辑,先执行第一个事务,如果阻塞了,会一直等待,直到这个事务完成,再执行第二个事务,顺序执行

异步是和同步相对的,异步是指在处理调用这个事务的之后,不会等待这个事务的处理结果,直接处理第二个事务去了,通过状态、通知、回调来通知调用者处理结果

asyncio函数:

异步IO采用消息循环的模式,重复“读取消息―处理消息”的过程,也就是说异步IO模型”需要一个消息循环,在消息循环中,主线程不断地重复“读取消息-处理消息”这一过程。

event_loop 事件循环:程序开启一个无限的循环,程序员会把一些函数注册到事件循环上。当满足事件发生的时候,调用相应的协程函数。

coroutine 协程:协程对象,指一个使用async关键字定义的函数,它的调用不会立即执行函数,而是会返回一个协程对象。协程对象需要注册到事件循环,由事件循环调用。

task 任务:一个协程对象就是一个原生可以挂起的函数,任务则是对协程进一步封装,其中包含任务的各种状态。

async/await 关键字: 用于定义协程的关键字,async定义一个协程,await用于挂起阻塞的异步调用接口。

一、asyncio

下面通过举例来对比同步代码和异步代码编写方面的差异,其次看下两者性能上的差距,使用asyncio.sleep(1)模拟耗时1秒的io操作。

同步代码:

import timedef hello():  time.sleep(1)def run():  for i in range(5):    hello()    print('Hello World:%s' % time.time()) if __name__ == '__main__':  run()Hello World:1536842494.2786784Hello World:1536842495.2796268Hello World:1536842496.2802596Hello World:1536842497.2804587Hello World:1536842498.2812462

异步代码:

import timeimport asyncio# 定义异步函数async def hello():  print('Hello World:%s' % time.time())  #必须使用await,不能使用yield from;如果是使用yield from ,需要采用@asyncio.coroutine相对应  await asyncio.sleep(1)    print('Hello wow World:%s' % time.time())def run():  tasks = []  for i in range(5):    tasks.append(hello())  loop.run_until_complete(asyncio.wait(tasks))loop = asyncio.get_event_loop()if __name__ =='__main__':  run()Hello World:1536855050.1950748Hello World:1536855050.1950748Hello World:1536855050.1950748Hello World:1536855050.1960726Hello World:1536855050.1960726(暂停约1秒)Hello wow World:1536855051.1993241Hello wow World:1536855051.1993241Hello wow World:1536855051.1993241Hello wow World:1536855051.1993241Hello wow World:1536855051.1993241

async def 用来定义异步函数,其内部有异步操作。每个线程有一个事件循环,主线程调用asyncio.get_event_loop()时会创建事件循环,把异步的任务丢给这个循环的run_until_complete()方法,事件循环会安排协同程序的执行。

上述程序中,hello()会首先打印出Hello world!,然后,yield from语法可以让我们方便地调用另一个generator。

由于await asyncio.sleep(1)也是一个coroutine,所以线程不会等待asyncio.sleep(1),而是直接中断并执行下一个消息循环。

当asyncio.sleep(1)返回时,线程就可以从yield from拿到返回值(此处是None),然后接着执行下一行语句。

把asyncio.sleep(1)看成是一个耗时1秒的IO操作,在此期间,主线程并未等待,而是去执行EventLoop中其他可以执行的coroutine了,因此可以实现并发执行。

asyncio操作的总结:

async def hello(): 定义async异步函数,中间可以添加await async.sleep(N) 来设定中断并执行下一个循环消息

tasks = [] 任务则是对协程进一步封装,其中包含任务的各种状态。即多个coroutine函数可以封装成一组Task然后并发执行

loop = asyncio.get_event_loop() #获取“事件循环”对象

loop.run_until_complete(asyncio.wait(tasks)) #通过事件循环,去调用协程函数

loop.close() 结束时间循环

二、aiohttp   

如果需要并发http请求,通常是用requests,但requests是同步的库,如果想异步的话需要引入aiohttp。

这里引入一个类,from aiohttp import ClientSession,首先要建立一个session对象,然后用session对象去打开网页。

session可以进行多项操作,比如post, get, put, head等。

基本用法:

async with ClientSession() as session:

async with session.get(url) as response:

aiohttp异步实现的例子:

import asynciofrom aiohttp import ClientSessiontasks = []url = "https://www.baidu.com/{}"async def hello(url):  async with ClientSession() as session:    async with session.get(url) as response:      response = await response.read()      print(response)if __name__ == '__main__':  loop = asyncio.get_event_loop()  loop.run_until_complete(hello(url))

首先async def 关键字定义了这是个异步函数,await 关键字加在需要等待的操作前面,response.read()等待request响应,是个耗IO操作。然后使用ClientSession类发起http请求。

多链接异步访问

如果我们需要请求多个URL该怎么办呢,同步的做法访问多个URL只需要加个for循环就可以了。但异步的实现方式并没那么容易,在之前的基础上需要将hello()包装在asyncio的Future对象中,然后将Future对象列表作为任务传递给事件循环。

import timeimport asynciofrom aiohttp import ClientSessiontasks = []url = "https://www.baidu.com/{}"async def hello(url):  async with ClientSession() as session:    async with session.get(url) as response:      response = await response.read()      print('Hello World:%s' % time.time())def run():  for i in range(5):    task = asyncio.ensure_future(hello(url.format(i)))    tasks.append(task)if __name__ == '__main__':  loop = asyncio.get_event_loop()  run()  loop.run_until_complete(asyncio.wait(tasks))Hello World:1536843566.064149Hello World:1536843566.070586Hello World:1536843566.0769563Hello World:1536843566.0779328Hello World:1536843566.0799286

・收集http响应

好了,上面介绍了访问不同链接的异步实现方式,但是我们只是发出了请求,如果要把响应一一收集到一个列表中,最后保存到本地或者打印出来要怎么实现呢,可通过asyncio.gather(*tasks)将响应全部收集起来

import timeimport asynciofrom aiohttp import ClientSessiontasks = []url = "https://www.baidu.com/{}"async def hello(url):  async with ClientSession() as session:    async with session.get(url) as response:#      print(response)      print('Hello World:%s' % time.time())      return await response.read()def run():  for i in range(5):    task = asyncio.ensure_future(hello(url.format(i)))    tasks.append(task)  result = loop.run_until_complete(asyncio.gather(*tasks))  print(result)if __name__ == '__main__':  loop = asyncio.get_event_loop()  run()Hello World:1536843488.678779Hello World:1536843488.6797836Hello World:1536843488.6867576Hello World:1536843488.6877556Hello World:1536843488.6877556

以上这篇python 异步async库的使用说明就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。


  • 上一条:
    在python里使用await关键字来等另外一个协程的实例
    下一条:
    Python插件机制实现详解
  • 昵称:

    邮箱:

    1条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客