【异步并发编程】使用aiohttp构建Web应用程序

【作者主页】:吴秋霖
【作者介绍】:Python领域优质创作者、阿里云博客专家、华为云享专家。长期致力于Python与爬虫领域研究与开发工作!
【作者推荐】:对JS逆向感兴趣的朋友可以关注《爬虫JS逆向实战》,对分布式爬虫平台感兴趣的朋友可以关注《分布式爬虫平台搭建与开发实战》
还有未来会持续更新的验证码突防、APP逆向、Python领域等一系列文章

1. 写在前面

  平时我们在使用Pythohn去开发REST API接口的时候,大部分人都会选择Flask、FastApi、Django

今天将使用aiohttp,一个基于异步I/O的Python框架,来构建REST API,相比于传统的同步框架Flask,看看它所带来的效果

在这里插入图片描述

1. 什么是aiohttp?

  aiohttp是Python中一款优秀的异步Web框架,它能够帮助我们构建高效的异步Web应用和异步HTTP客户端。允许我们同时处理大量并发请求,而不会阻塞程序执行。aiohttp使用Python的 async/await语法来实现异步编程,使得开发者能够轻松处理高并发的 I/O 操作,特别适用于构建需要实时性和高性能的应用程序,比如 Web 服务器、RESTful API、实时通信系统

关键组件与说明:

  • 异步I/O:aiohttp利用Python的asyncio实现了异步I/O操作,允许在单个线程中处理多个并发操作,提高了应用程序的性能
  • HTTP客户端:提供了强大的异步HTTP客户端,支持异步请求和响应,适用于与其他服务进行异步通信,例如调用RESTful API
  • HTTP服务器:内置了一个异步的HTTP服务器,可用于构建高性能的We 服务。它支持异步请求处理,使得服务器能够同时处理多个连接
  • WebSocket支持:aiohttp原生支持WebSocket 协议,方便构建实时通信和推送功能。
  • 中间件和拦截器: 提供了中间件和拦截器的支持,允许在请求处理的不同阶段添加自定义逻辑,增强了框架的可扩展性
  • 路由系统:支持定义灵活的路由,使得构建RESTful API 变得直观和简单

1.1. 什么是异步编程?

  这里我们用大白话,举例说一下到底什么是异步编程??首先我们想象一下,传统同步编程就像是在等公交车的排队,每个人都得按顺序上车,哪怕前面的人需要等待很长时间。但是异步编程就像是你在等待公交的时候,看到了一辆共享单车,你可以先骑着单车走一段路,不必等到公交来了再上车。这样一来,你既能享受风景,又能更高效地前行,同时不会傻傻地站在那里等待

  在传统同步编程中,一个任务的执行需要等待,就像大家得按次序上车一样,一旦有任务在等待,整个程序就像是陷入了拥堵,其他任务也只能束手待毙。但异步编程就不一样,它就像是程序里有了一些"超能力",当有任务需要等待时,它会像变魔术一样,让其他任务继续前行。这样就好比在拥挤的城市中,你能够巧妙地绕过人群,灵活自如地到达目的地,同时不受拥堵的影响。

所以,异步编程不仅是更高效的程序运行方式,更是一种程序的"超能力",让你的代码可以更灵活、更迅速地应对各种任务,就像是给你的程序穿上了一双闪电之靴,让它在处理任务时更为迅猛,不再受制于传统的等待方式

在 Python 的异步编程中,使用async/await来声明异步函数和执行异步操作。使用async关键字定义一个函数时,它将返回一个协程对象,而使用await关键字可以在协程中等待其他协程执行完成

  • 协程 (Coroutine):协程是一种可以暂停执行并在稍后恢复的函数,它允许我们在函数内部进行状态保存。在异步编程中,协程非常有用,因为它们允许我们在等待I/O操作的同时,执行其他任务
  • 事件循环 (Event Loop):事件循环是异步编程的核心,它是一个循环结构,负责不断地监听并处理事件。在Python中,可以使用asyncio模块提供的事件循环来驱动异步协程的执行

2. 安装aiohttp

在开始使用aiohttp之前,我们需要先安装它。可以使用pip进行安装:

1、检查python版本:

$ python3 -V
Python 3.9.7

2、安装aiohttp:

$ pip3 install aiohttp

3、检aiohttp版本号:

$ python3 -c "import aiohttp; print(aiohttp.__version__)"
3.7.4

3. 异步HTTP服务器

  aiohttp提供了两个关键模块:aiohttp.webaiohttp.client,分别用于构建 Web 应用程序和创建异步 HTTP 客户端

让我们先聚焦于aiohttp.web模块,它是构建异步Web应用程序的骨干。下面是一个简单而强大的异步HTTP服务器示例:

import asyncio
from aiohttp import web

async def handle(request):
    return web.Response(text="Hello, 欢迎来到我的博客!")

app = web.Application()
app.router.add_get('/', handle)

# 手动启动事件循环
async def start_app():
    runner = web.AppRunner(app)
    await runner.setup()
    site = web.TCPSite(runner, 'localhost', 8080)
    await site.start()

if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    try:
        loop.run_until_complete(start_app())
        loop.run_forever()
    except KeyboardInterrupt:
        pass
    finally:
        loop.run_until_complete(loop.shutdown_asyncgens())
        loop.close()

运行以上代码,你将会看到aiohttp服务器已经在本地运行,并且正在监听默认端口。当你在浏览器中访问localhost+端口即可

4. 异步请求

  除了作为异步 Web 服务器,aiohttp 还为我们提供了强大的异步HTTP客户端,用于方便地向其他服务器发起异步请求。以下是一个简单而强大的例子:

import aiohttp
import asyncio

async def fetch(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            return await response.text()

async def main():
    url = 'https://www.baidu.com'
    result = await fetch(url)
    print(result)

asyncio.run(main())

在上述代码中,我们定义了一个fetch函数,它利用aiohttp的 ClientSession对象发起一个异步的GET请求,并返回响应内容。在 main函数中,我们调用fetch函数并输出结果。

这个简单的例子展示了aiohttp如何轻松地使异步HTTP客户端请求变得简单。通过aiohttp的异步特性,我们可以高效地与其他服务器进行通信,而不会阻塞主程序的执行。这为构建异步、高性能的网络应用提供了一种便捷而强大的方式

5. aiohttp REST实例

  REST(Representational State Transfer)是现代Web应用程序开发中广泛使用的规范,尤其是在与具有React和Vue等框架的单页应用程序结合使用时。REST提供了一种无状态、结构化的设计方式,独立于客户端技术,使得Web API的开发更为简便。REST API应该能够与从手机到浏览器的任意数量的客户端进行互操作,并且只需要更改数据的客户端表示即可。

在REST中,关键概念是资源。资源通常可以用名词表示,例如客户、产品或账户,它们可以是RESTful资源。资源可以是单个实例,如单个客户或产品,也可以是集合。例如,具有一些唯一标识符的单个客户或产品可以被视为集合中的一个资源。此外,资源也可能有子资源。以客户的最喜欢产品列表为例,这个列表就是客户的子实体。以下是几个REST API的示例,以更好地理解这些概念:

customers
customers/{
    
    id}
customers/{
    
    id}/favorites

这里有三个REST API端点。第一个端点customers代表一组客户,我们期望它返回一个客户列表。第二个端点代表一个客户,并通过{id}参数指定客户的唯一标识符。调用customers/1将返回id为1的客户的数据。最后一个端点是子实例的示例,即客户的收藏列表。调用 customers/1/favorites 将返回id为1的客户的收藏列表。

设计REST API时,通常选择使用JSON作为数据格式,因为这是典型的用法。虽然REST API有时可以通过HTTP标头的设置来支持多种数据表示,但理解REST的所有细节将有助于更好地应用这一设计方式

from aiohttp import web
import json

async def get_users(request):
    users = [{
    
    'id': 1, 'name': 'Alice'}, {
    
    'id': 2, 'name': 'Bob'}]
    return web.json_response(users)

async def get_user(request):
    user_id = request.match_info['id']
    user = {
    
    'id': int(user_id), 'name': 'User ' + user_id}
    return web.json_response(user)

app = web.Application()
app.router.add_get('/users', get_users)
app.router.add_get('/users/{id}', get_user)

if __name__ == '__main__':
    web.run_app(app, port=8080)

在这里插入图片描述

在这个示例中:

  • get_users函数用于处理获取用户列表的请求,返回一个包含用户信息的JSON响应
  • get_users函数用于处理获取特定用户信息的请求,根据请求中的用户ID返回对应用户的JSON响应
  • 其中创建了一个web.Application()对象,并通过app.router.add_get方法定义了两个端点,分别对应/users/users/{id}
  • 最后使用web.run_app启动应用,监听在本地的8080端口

  好了,到这里又到了跟大家说再见的时候了。创作不易,帮忙点个赞再走吧。你的支持是我创作的动力,希望能带给大家更多优质的文章

猜你喜欢

转载自blog.csdn.net/qiulin_wu/article/details/134337933