Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4562467
  • 博文数量: 1214
  • 博客积分: 13195
  • 博客等级: 上将
  • 技术积分: 9105
  • 用 户 组: 普通用户
  • 注册时间: 2007-01-19 14:41
个人简介

C++,python,热爱算法和机器学习

文章分类

全部博文(1214)

文章存档

2021年(13)

2020年(49)

2019年(14)

2018年(27)

2017年(69)

2016年(100)

2015年(106)

2014年(240)

2013年(5)

2012年(193)

2011年(155)

2010年(93)

2009年(62)

2008年(51)

2007年(37)

分类: Python/Ruby

2021-03-06 22:04:12


0x00 协程

asyncio和gevent都是基于携程来进行并发操作的。协程也被称为微线程。
协程只是在单一的线程里进行切换不同的协程,因此无法使用多CPU能力,对于CPU密集型程序还是使用多进程比较好。
协程相比较进程和线程来说占用的内容更少,同样的线程切换更多的是靠操作系统来控制,而协程的执行则由我们自己控制。
并发原理:当其中一个协程遇到io等待时,将会切换到另一个协程继续运行。

0x01 grequests

grequests是对requests和gevent库的封装
测试代码:

#!/usr/bin/python3.7 import grequests import time if __name__ == '__main__': start = time.time() greenlets = [] for _ in range(10): greenlets.append(grequests.get("")) rets = grequests.map(greenlets) for ret in rets: print(ret) end = time.time() print("grequests visit_async tasks %.2f seconds" % (end - start)) 

grequests.map()参数说明:
def grequests.map(requests, stream=False, size=None, exception_handler=None, gtimeout=None)

参数 说明 备注
size 协程的并发度(相当于线程数) 当一个协程在IO等待时,会将CPU交给其他协程
exception_handler 异常处理函数 用于处理单个请求出现异常的函数
gtimeout 设置所有请求的超时时间

grequests的底层是request,所以它也支持回调函数:

def print_url(r, *args, **kwargs): print(r.url) res = grequests.get(url, callback=print_url) 



测试结果:
grequsts并发性能测试

0x02 asyncio + uvloop

由于gevent的猴子补丁的缘故,requests可以和gevent结合使用,但是在不清楚内部实现的情况下,requests库经常比较容易出现Failed to establish a new connection:的情况,在使用grequests库之后该情况得到解决。
uvloop是用Cython写的,目前不支持windows,它基于libuv.uvloop使得asyncio更快,基于性能的测试接近于go。
可以通过两种方式来使用uvloop:

import uvloop import asyncio #1. 通过设置策略 asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) #2. 直接创建一个新的event_loop asyncio.set_event_loop(uvloop.new_event_loop()) 

由于asycnio采用异步操作,它在使用的过程中所有的模块也都得是异步的,所以在进行http请求时也需要异步,即aiohttp
测试代码:

#!/usr/bin/python3.7 import asyncio import aiohttp import uvloop import time async def access_url(url): async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=False)) as session: async with session.get(url) as response: status_code = response.status print(status_code) async def visit_async(): start = time.time() tasks = [] for _ in range(10): tasks.append(access_url("")) await asyncio.gather(*tasks) end = time.time() print("asyncio visit_async tasks %.2f seconds" % (end - start)) if __name__ == '__main__': loop = asyncio.get_event_loop() future = asyncio.ensure_future(visit_async()) asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) loop.run_until_complete(future) 



测试结果:
asyncio 并发性能测试

0x03 优缺点

asyncio由于是异步操作,且代码库生态不够完善,部分异步代码库存在问题可能查不到,且编写代码时行数较多,影响阅读,而且代库函数全部重构,上手有难度,但是并发执行的速度较快,对于暴破、端口扫描等比较适用。
gevent采用了requests模块,在使用了猴子补丁后对于扫描网站路径等可以有效即时针对扫描结果进行深层扫描。

请求内容:


请求内容

参考:




阅读(2329) | 评论(0) | 转发(0) |
0

上一篇:scala-json

下一篇:Spark之pipeline机制

给主人留下些什么吧!~~