星星博客 »  > 

Python 全栈系列103 -异步请求获取asyncio

说明

异步函数写起来还是挺不方便的,特别是在jupyter里面的调用又有点不同(jupyter默认起了一个loop,那个loop还不好关)

文章一 在ipython中
文章二 在jupyter中

在这里插入图片描述

内容

1 用法

以一个get任务为例,在jupyter中这么写就可以。主要是不用去管loop。

  • 1 jupyter
import aiohttp
import asyncio
import json
async def fetchx(x,url_template):
    async with aiohttp.ClientSession() as session:
        async with session.get(url_template % x) as response:
            res = await response.text()
            
    return {x:json.loads(res)}

# 获取solr的文书,创建异步任务
def make_async_task_list(doc_id_list, url_template):
    tasks = []
    for  doc_id in doc_id_list:
        task = asyncio.ensure_future(fetchx(doc_id, url_template))
        tasks.append(task)
    return tasks

query_tasks = make_async_task_list(doc_id_list, query_template)

response_list = await asyncio.gather(*query_tasks)
  • 2 py文件

这个还是我从自己的老黄历里面找到改过来的,反正调试各种坑,实在没时间研究这个。能用就行。

import aiohttp
import asyncio
import json
async def fetchx(x,url_template):
    async with aiohttp.ClientSession() as session:
        async with session.get(url_template % x) as response:
            res = await response.text()
    return {x:json.loads(res)}


async def async_query_main(doc_id_list, url_template, loop):
    tasks = []
    res = []
    
    for doc_id in doc_id_list:
        tasks.append(asyncio.ensure_future(fetchx(doc_id,url_template ),loop=loop))
    await asyncio.wait(tasks)
    for task in tasks:
        res.append(task.result())
    return res 
    
def run_async_query(doc_id_list, query_template):
    start = time.time()
    # loop = asyncio.new_event_loop()
    # asyncio.set_event_loop(loop)
    loop = asyncio.get_event_loop()

    res = loop.run_until_complete(async_query_main(doc_id_list, query_template, loop))
    # loop.close()
    print('Async Query Run Spending : {} s'.format(time.time() - start))
    return res
    
a = run_async_query(doc_id_list, query_template)

2 效果

这个蛮有意思的。我们先看看同步方式。jupyter,使用docker镜像方式启动。

耗时稳定,1秒多一点。

import requests as req
start = time.time()
for i in range(500):
    the_s = query_template % doc_id_list[i]
    req.get(the_s)
print('taske %.6f' %(time.time()- start))
---
taske 1.079582

jupyter方式,使用docker镜像方式启动

测试了10,7次的时间从0.22~0.28, 3次的时间在1.18左右

start = time.time()
query_tasks = fs.make_async_task_list(doc_id_list,query_template)
response_list = await asyncio.gather(*query_tasks)
print('taske %.6f' %(time.time()- start))
---
taske 0.286131 7---taske 1.188181 3

python老黄历方式

大部分在0.35, 有时不到0.3。

在这里插入图片描述
总体上这三者的比较是公平的:

  • 1 同步不用构造任务,就是请求
  • 2 两种异步方式都包含了构造任务的时间
  • 3 老黄历的方法似乎也有一些可取之处,但是和jupyter方法的实现机制肯定有不同

3 总结

  • 1 jupyter和py的方式是不同的,主要是loop的原因,但是两者都要用
  • 2 本测试是在内网下,网络已经非常通畅(同步几乎无阻塞),但是异步方式比同步还是要快一倍以上

相关文章