Python使用async/await/aiohttp实现简单请求并发

前言

之前工作的时候从大佬那里学习到的一点异步并发代码分享给大家使用,直接复制粘贴就可以了。

import asyncio
import logging

import aiohttp

logging.basicConfig(format='[%(asctime)s] %(message)s', level=logging.INFO)

task_count = 0


async def async_get(url, out_type='text', **kwargs):
    """
    模拟发送GET请求 异步实现
    :param url:
    :param out_type:
    :param kwargs:
    :return:
    """
    return_info = {
    
    }
    try:
        """
        设置超时时间(
        total: 整个请求的超时时间,包括连接建立、请求发送、响应接收等所有阶段。如果在该时间内请求没有完成,就会抛出超时异常。在这个例子中,超时时间为10秒。
        connect: 连接建立的超时时间。如果在该时间内连接没有建立成功,就会抛出超时异常。在这个例子中,连接建立的超时时间为2秒。
        sock_connect: socket连接建立的超时时间。如果在该时间内socket连接没有建立成功,就会抛出超时异常。在这个例子中,socket
        连接建立的超时时间为5秒。
        sock_read: socket接收数据的超时时间。如果在该时间内没有接收到数据,就会抛出超时异常。在这个例子中,socket
        接收数据的超时时间为5秒。
        )
        """
        timeout = aiohttp.ClientTimeout(total=10, connect=2, sock_connect=5, sock_read=5)
        # 使用async with创建客户端(会自动关闭,所以我的main函数没有添加close,不然会报错)
        async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(limit=100, ssl=False),
                                         timeout=timeout) as session:
            async with session.get(url, **kwargs) as resp:
                if resp and resp.status == 200:
                    if out_type == 'text':
                        data = await resp.text()
                    elif out_type == 'bytes':
                        data = await resp.content.read()
                    elif out_type == 'json':
                        data = await resp.json()
                    return_info['text'] = data
                    return_info['url'] = resp.url
                    return_info['headers'] = resp.headers
                    return_info['status'] = resp.status
                    return_info['cookies'] = resp.cookies
                    return return_info
    except Exception as e:
        logging.info(f"地址访问异常:{
      
      url}-{
      
      e}")
    return return_info


async def async_post(url, out_type='json', **kwargs):
    """
    模拟发送POST请求 异步实现
    :param url:
    :param out_type:
    :param kwargs:
    :return:
    """
    return_info = {
    
    }
    try:
        """
        设置超时时间(
        total: 整个请求的超时时间,包括连接建立、请求发送、响应接收等所有阶段。如果在该时间内请求没有完成,就会抛出超时异常。在这个例子中,超时时间为10秒。
        connect: 连接建立的超时时间。如果在该时间内连接没有建立成功,就会抛出超时异常。在这个例子中,连接建立的超时时间为2秒。
        sock_connect: socket连接建立的超时时间。如果在该时间内socket连接没有建立成功,就会抛出超时异常。在这个例子中,socket
        连接建立的超时时间为5秒。
        sock_read: socket接收数据的超时时间。如果在该时间内没有接收到数据,就会抛出超时异常。在这个例子中,socket
        接收数据的超时时间为5秒。
        )
        """
        timeout = aiohttp.ClientTimeout(total=10, connect=2, sock_connect=5, sock_read=5)
        # 使用async with创建客户端(会自动关闭,所以我的main函数没有添加close,不然会报错)
        async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(limit=100, ssl=False),
                                         timeout=timeout) as session:
            async with session.post(url, **kwargs) as resp:
                if resp and resp.status == 200:
                    if out_type == 'json':
                        data = await resp.text()
                    elif out_type == 'text':
                        data = await resp.json()
                    return_info['text'] = data
                    return_info['url'] = resp.url
                    return_info['headers'] = resp.headers
                    return_info['status'] = resp.status
                    return_info['cookies'] = resp.cookies
                    return return_info
    except Exception as e:
        logging.info(f"地址访问异常:{
      
      url}-{
      
      e}")
    return return_info


async def get_url(url):
    global task_count
    res = await async_get(url)
    # print(res)
    task_count -= 1
    return res


async def main():
    global task_count
    # 任务数量,可以从redis读取
    urls = ['https://www.baidu.com/', 'https://www.baidu.com/', 'https://www.apple.com/'] * 5
    # 并发数量
    max_task_count = 10
    while True:
        # 控制并发
        free_count = max_task_count - task_count
        if free_count:
            logging.info(
                "系统当前正在执行任务数:{},未达到最大并发数:{},即将加载新的待执行任务...".format(task_count + 1,
                                                                                                 max_task_count))
            # 检查是否还有数据
            if urls:
                url = urls.pop()
                task = asyncio.create_task(get_url(url))
                # 运行一次增加一次并发任务量
                task_count += 1
            else:
                logging.info('没有等待检测的url...')
                await asyncio.sleep(1)
        else:
            await asyncio.sleep(1)


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

猜你喜欢

转载自blog.csdn.net/qq_41866988/article/details/131284771
今日推荐