C++,python,热爱算法和机器学习
全部博文(1214)
分类: Python/Ruby
2021-03-06 22:04:12
asyncio和gevent都是基于携程来进行并发操作的。协程也被称为微线程。
协程只是在单一的线程里进行切换不同的协程,因此无法使用多CPU能力,对于CPU密集型程序还是使用多进程比较好。
协程相比较进程和线程来说占用的内容更少,同样的线程切换更多的是靠操作系统来控制,而协程的执行则由我们自己控制。
并发原理:当其中一个协程遇到io等待时,将会切换到另一个协程继续运行。
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)
由于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由于是异步操作,且代码库生态不够完善,部分异步代码库存在问题可能查不到,且编写代码时行数较多,影响阅读,而且代库函数全部重构,上手有难度,但是并发执行的速度较快,对于暴破、端口扫描等比较适用。
gevent采用了requests模块,在使用了猴子补丁后对于扫描网站路径等可以有效即时针对扫描结果进行深层扫描。
请求内容:
参考: