相关推荐recommended
FastAPI 库(Python 的 Web 框架)基本使用指南(一)
作者:mmseoamin日期:2023-12-02

FastAPI 概述

参考文档:

  • 中文文档
  • 轻松上手Python的Web神器:FastAPI教程

    介绍

    FastAPI 是一个基于 Python 的现代 Web 框架,它具有快速构建高性能 API 的特点。

    FastAPI 关键特性:

    • 快速:可与 NodeJS 和 Go 并肩的极高性能(归功于 Starlette 和 Pydantic)。最快的 Python web 框架之一。
    • 高效编码:提高功能开发速度约 200% 至 300%。
    • 更少 bug:减少约 40% 的人为(开发者)导致错误。
    • 智能:极佳的编辑器支持。处处皆可自动补全,减少调试时间。
    • 简单:设计的易于使用和学习,阅读文档的时间更短。
    • 简短:使代码重复最小化。通过不同的参数声明实现丰富功能。bug 更少。
    • 健壮:生产可用级别的代码。还有自动生成的交互式文档。
    • 标准化:基于(并完全兼容)API 的相关开放标准:OpenAPI (以前被称为 Swagger) 和 JSON Schema。

      常见 Python Web 框架的介绍与区别

      性能:

      • Django:是一个全功能的框架,它提供了许多内置的功能和扩展。虽然它在性能方面相对较低,但它非常适合构建大型应用程序。

      • Flask:是一个轻量级的框架,它更加注重简洁和灵活性。相比于 Django,Flask 具有更好的性能表现,但它的功能相对较少。

      • FastAPI:是一个高性能的框架,它基于异步请求处理和类型注解。FastAPI 比 Django 和 Flask 在性能上更为出色,并且它使用 Python 的 asyncio 库来实现高效的并发请求处理。

        开发难度:

        • Django:是一个全功能的框架,它提供了许多现成的功能和组件,使得开发更加快速和简单。但是,对于初学者来说,Django的学习曲线可能相对较陡。
        • Flask:是一个简洁而灵活的框架,它更多地侧重于自定义和配置。相对于 Django,Flask 的学习曲线较为平缓,适合小型和简单的项目。
        • FastAPI:使用了类型注解和自动生成文档的功能,使代码更易读和维护。它提供了基于标准的API模式和强大的验证工具,减少了开发过程中的错误。

          推广程度:

          • Django:是最受欢迎和广泛使用的 Python Web 框架之一。它拥有庞大的社区支持和丰富的文档资源,可以轻松找到相关的教程、插件和解决方案。

          • Flask:是一个比较受欢迎的框架,拥有庞大的社区和丰富的扩展库。虽然它的用户群体相对较小,但在小型项目和快速原型开发中非常流行。

          • FastAPI:是一个相对较新的框架,但它正在迅速获得开发者的关注。它的高性能和现代特性吸引了许多开发者,并且社区正在逐渐扩大。

            FastAPI 是一个用于构建 API 的现代、快速(高性能)的 web 框架,使用 Python 3.6+ 并基于标准的 Python 类型提示。

            入门示例

            • 安装 FastAPI 和 uvicorn

              FastAPI 使用 uvicorn 作为默认的 Web 服务。因此,需要在安装 FastAPI 和 uvicorn

              uvicorn 是一个轻量级的 ASGI(异步服务器网关接口)服务器

              pip install fastapi
              pip install uvicorn
              
            • 示例代码

              from fastapi import FastAPI
              import uvicorn
              # 创建一个FastAPI应用程序实例
              app = FastAPI()
              # 定义路由(使用装饰器将函数绑定到特定的路径和HTTP方法)
              @app.get("/")
              async def root():
                  return {"message": "Hello World"}
              @app.get("/items/{item_id}")
              def read_item(item_id: int, q: str = None):
                  return {"item_id": item_id, "q": q}
              # 启动程序时使用 uvicorn 允许 FastAPI 应用程序
              uvicorn.run(app)
              # 默认ip为127.0.0.1,默认端口为8000
              

              启动 web 服务

              • 方式1:uvicorn 内嵌式

                在代码中使用 uvicorn.run(app) 启用 uvicorn 服务器运行 python 服务,然后使用 python 启动 py 模块

                import uvicorn
                app = FastAPI()
                uvicorn.run(app)
                
              • 方式2:uvicorn 外启式

                在命令行输入命令:

                uvicorn main:app --host 0.0.0.0 --port 80 --reload
                
                • main:启动服务的py文件名
                • app:服务对象名
                • –-host:ip地址
                • –-port:端口
                • –-reload:代码修改后自动重启服务。仅在开发时使用,上线后不要带这个参数,会降低性能

                  uvicorn.run 支持的参数

                  • app :指定应用 app。‘脚本名:FastAPI 实例对象’ 或 FastAPI 实例对象
                  • host :字符串,允许被访问的形式:locahost、127.0.0.1、当前 IP、0.0.0.0。默认为127.0.0.1
                  • port :数字,应用的端口,默认为 8000
                  • uds :字符串,socket 服务绑定到 UNIX 的域名
                  • fd :数字,从此文件描述符绑定到socket
                  • loop :事件循环模式。选项列表为 [auto|asyncio|uvloop],默认为 auto
                  • http :HTTP协议实现。选项列表为 [auto|h11|httptools],默认为auto
                  • ws :WebSocket协议实现。选项列表为 [auto|none|websockets|wsproto],默认为auto
                  • ws-max-size :数字,WebSocket 最大消息大小(字节),默认值为 16777216
                  • lifespan :生命周期实施。选项列表为 [auto|on|off],默认为auto
                  • env-file :PATH,环境配置文件
                  • log-config :PATH,日志配置文件。支持的格式:.ini、.json、.yaml,默认为 fastapi 默认的 log 配置
                  • log-level :日志级别。选项列表为 [critical|error|warning|info|debug|trace],默认 info
                  • access-log :boolean,access log 日志的开关,默认为 True
                  • use-colors :boolean,彩色日志的开关(前提需指定log-config),默认为 None
                  • interface :选择 ASGI3、ASGI2 或 WSGI 作为应用程序接口。选项列表为 [auto|asgi3|asgi2|wsgi],默认为 auto
                  • debug :是否使用 debug 模式,默认False,
                  • reload :boolean,当代码发生更时,是否自动重启,默认 False,
                  • reload_dirs :字符串,设置重新加载目录,当没有传这个参数的实时,将取当前工作目录
                  • reload-delay :float,每隔多久检测代码是否有变动,默认 0.25 秒
                  • workers :数字,工作进程数。默认为 WEB_CONCURRENCY 环境变量(如果可用) 或 1。对于 --reload 无效。
                  • proxy-headers :boolean,启用/禁用 X-Forwarded-Proto、X-Forwarded-For、X-Forwarded-Port 以填充远程地址信息,默认为 True
                  • forwarded-allow-ips :字符串,用逗号分隔的IP列表以信任代理标头。默认为 FORWARDED_ALLOW_IPS 环境变量(如果可用),或 None,为 None 时,代码里面则取 127.0.0.1
                  • root-path :字符串,为安装在给定 URL 路径下的应用程序设置 ASGI “根路径”。
                  • limit-concurrency :数字,在发出 HTTP503 响应之前,允许的最大并发连接数或任务数。默认为 None
                  • limit-max-requests :数字,达到多少请求数则终止进程,默认为 None
                  • backlog :数字,等待处理的最大连接数,默认为 2048
                  • timeout-keep-alive :数字,如果在此超时时间内未收到新数据,则关闭保持活动状态的连接,默认为 5
                  • ssl-keyfile :字符串,SSL密钥文件,默认为 None
                  • ssl-certfile :字符串,SSL证书文件,默认为 None
                  • ssl-keyfile-password :字符串,SSL密钥文件密码,默认为 None
                  • ssl-version :数字,要使用的 SSL版本(详见 stdlib SS L模块),默认为 2
                  • ssl-cert-reqs :数字,是否需要客户端证书(详见 stdlib SSL 模块),默认为 0
                  • ssl-ca-certs :字符串,CA 证书文件
                  • ssl-ciphers :字符串,要使用的 CA 证书文件密码(详见 stdlib SSL 模块),默认为 TLSv1
                  • header :字典,自定义响应头信息,键值对的形式,默认为 None

                    常用 API

                    app=FastAPI() :创建 FastAPI 应用程序实例

                    • app = FastAPI() 是在 FastAPI 中创建应用程序实例的常见做法。这行代码创建了一个 FastAPI 应用程序对象,可以在这个对象上定义路由、中间件、异常处理等。

                    • 应用程序实例 app 具有许多属性和方法,用于配置和管理应用程序的各个方面,如路由、中间件、异常处理、依赖注入等。通过创建 app 实例,可以在其中定义和组织应用程序的逻辑。

                    • 代码示例

                      from fastapi import FastAPI
                      app = FastAPI()
                      
                    • 支持参数(均为可选传):

                      • debug :调试模式,True/False。此属性继承自 starlette,在 starlette 中使用的是 property 装饰器

                      • routes :路由列表,默认值为 None

                        此属性继承自 starlette,类型为 startlette 的 BaseRoute 列表,BaseRoute 与 starlette 的基础类型 Scope 有关

                      • title :API文档的标题,默认值 FastAPI

                      • description :API文档的描述,默认为空

                      • version :API 接口的版本号

                      • openapi_url :OpenAPI 文件路径,默认为 /opanapi.json

                      • openapi_prefix :OpenAPI 文件路径前缀,默认为空

                      • default_response_class :默认响应类型,默认为 JSONResponse

                        此参数继承自 startlette 的 Response,有 HTMLResponse、PlainTextResponse、UJSONResponse、RedirectResponse、StreamingResponse、FileResponse 和 JSONResponse 七种,使用时需加载 starlette.responses 模块

                      • docs_url :交互式文档路径,默认为 /docs

                      • redoc_url :可选式文档路径,默认为 /redoc

                      • swagger_ui_oauth2_redirect_url :OAuth 重定向路径,默认为 /docs/oauth2-redirect

                      • swagger_ui_init_oauth :OAuth 重定向字典,默认为 None

                      • middleware :中间件,默认为空

                      • exception_handlers :异常处理方法,默认为 None

                      • on_startup :app 启动时调用的方法列表

                      • on_shutdown :app 关闭时调用的方法列表

                      • extra : 额外可选参数

                        FastAPI() 实例常用 API

                        get()、post() 等:定义 HTTP 请求的路由

                        在 FastAPI 中,app.get() 、app.post()等方法用于定义 HTTP 请求的路由。这些方法接受多个参数,用于指定路由的路径、请求处理函数、依赖项等。

                        以下是主要参数:

                        • path(必填):用于指定路由的路径。这是一个字符串,表示 URL 路径,可以包含路径参数和查询参数。
                        • response_model:用于指定响应模型。响应模型是响应数据的数据结构,通常使用 Pydantic 模型来定义。
                        • summary:一个简短的字符串,用于描述路由的目的或功能。
                        • description:用于提供更详细的路由说明。
                        • tags:一个字符串列表,用于标记路由,以便在文档中分类和组织路由。
                        • dependencies:一个列表,指定在路由处理函数中需要注入的依赖项。
                        • response_description:用于指定响应的描述信息。
                        • deprecated:一个布尔值,表示路由是否已被弃用。
                        • status_code:用于指定响应的 HTTP 状态码。
                        • response_model_include 和 response_model_exclude:用于指定在响应模型中包含或排除的字段。
                        • response_model_by_alias:一个布尔值,表示是否使用 Pydantic 模型中的别名来序列化响应。
                        • response_model_exclude_unset:一个布尔值,表示在响应中排除未设置的字段。
                        • response_model_exclude_defaults:一个布尔值,表示在响应中排除具有默认值的字段。
                        • response_model_exclude_none:一个布尔值,表示在响应中排除值为 None 的字段。
                        • operation_id:用于指定操作的唯一标识符。
                        • deprecated:一个布尔值,表示路由是否已被弃用。
                        • callbacks:一个字典,用于指定回调函数。

                          这些参数可以根据需求来灵活配置。一般来说,path 参数是必需的,而其他参数则根据需要来选择性地使用。

                          add_middleware():添加中间件

                          • add_middleware() 函数:是 FastAPI 中用于添加中间件的方法。

                            中间件是一种可以在请求和响应处理过程中进行预处理和后处理的功能。可以使用中间件来实现各种需求,如添加全局头部、请求日志记录、异常处理等。

                            通过 app.add_middleware 方法将自定义中间件添加到应用程序。当请求到达时,FastAPI 会依次执行添加的中间件,然后再调用路由处理函数。在响应返回时,会按照相反的顺序执行中间件的后处理逻辑。

                            通过添加中间件,可以在请求和响应处理过程中实现一些通用的功能,而不需要在每个路由中重复编写相同的代码。这有助于保持代码的整洁和可维护性。

                          • 常用参数:

                            • middleware_class(必需):一个中间件类,希望添加到应用程序的中间件。

                              中间件类应继承自 fastapi.middleware.base.BaseHTTPMiddleware 或类似的基类。

                            • **options:这是中间件的配置选项,可以根据中间件的要求传递不同的参数。具体的选项取决于使用的中间件类。通常,可以传递任何与中间件相关的自定义参数,以便在中间件类中使用。

                              CORSMiddleware 中间件

                              • FastAPI 内置的中间件,用于处理跨源资源共享(CORS)问题。

                                CORS 是一种浏览器安全机制,用于控制跨域请求。在前端和后端分离的应用中,当前端代码(在浏览器中运行)从一个域向另一个域发出请求时,浏览器会执行跨域检查,确保只有受信任的域可以访问资源。

                                CORSMiddleware 可以帮助开发者配置 FastAPI 应用程序以正确处理跨域请求。

                                配置完中间件后,FastAPI 会自动处理跨域请求,并在响应中添加适当的头部信息以满足 CORS 安全要求。

                                请注意,CORS 配置涉及到应用程序的安全性。在生产环境中,应根据实际需求来配置 allow_origins 和其他参数。

                              • 常用参数(用于配置跨域策略):

                                • allow_origins:允许访问资源的域名列表。

                                  可以使用 ["*"] 表示允许所有域名,但这通常不是推荐的做法。

                                • allow_credentials:是否允许发送凭据(如 cookie、HTTP 认证头部)的请求。

                                  如果为 True,则需要确保在客户端和服务器端都进行相应的配置,且 allow_origins 必须为具体的源,不可以是 ["*"]

                                • allow_methods:允许的 HTTP 方法列表如 ["GET", "POST"]。默认是 ["GET"]

                                  可以使用 ["*"] 表示允许所有方法

                                • allow_headers:允许的 HTTP 头部列表,如 ["Content-Type", "Authorization"]。默认是 []

                                  可以使用 ["*"] 表示允许所有头部

                                  注:Accept、Accept-Language、Content-Language 以及 Content-Type 总是被允许的

                                • 代码示例:

                                  from fastapi import FastAPI
                                  from fastapi.middleware.cors import CORSMiddleware
                                  app = FastAPI()
                                  # 添加 CORS 中间件
                                  app.add_middleware(
                                      CORSMiddleware,
                                      allow_origins=["http://localhost", "https://example.com"],
                                      allow_credentials=True,
                                      allow_methods=["*"],
                                      allow_headers=["*"],
                                  )
                                  

                                  自定义中间件:

                                  • 方式1:自定义中间件类,添加自定义中间件时通过 dispatch 参数传递自定义中间件类的对象

                                    from fastapi import FastAPI, Request
                                    from fastapi.middleware.cors import BaseHTTPMiddleware
                                    # 自定义中间件
                                    class MyMiddleware:
                                        def __init__(self, some_attribute: str = None):
                                            # some_attribute非必需,此处用于演示传参到自定义的中间件
                                            self.some_attribute = some_attribute
                                        async def __call__(self, request: Request, call_next):
                                            # do something with the request object
                                            # process the request and get the response    
                                            response = await call_next(request)
                                            # do something with the response object
                                            return response
                                    app = FastAPI()
                                    # 添加自定义中间件
                                    app.add_middleware(BaseHTTPMiddleware, dispatch=MyMiddleware())
                                    
                                  • 方式2:自定义中间件类继承 BaseHTTPMiddleware 类

                                    # 自定义中间件
                                    class MyMiddleware(BaseHTTPMiddleware):
                                        def __init__(self, app, some_attribute: str):
                                            super().__init__(app)
                                            self.some_attribute = some_attribute
                                        async def dispatch(self, request: Request, call_next):
                                            # do something with the request object, for example
                                            content_type = request.headers.get('Content-Type')
                                            print(content_type)
                                            
                                            # process the request and get the response    
                                            response = await call_next(request)
                                            
                                            return response
                                    app = FastAPI()
                                    # 添加自定义中间件
                                    app.add_middleware(MyMiddleware)
                                    
                                  • 方式3:@app.middleware 装饰器

                                    在 FastAPI 中,可以使用 @app.middleware 装饰器来添加应用程序范围的中间件。

                                    即使用 @app.middleware 装饰器添加的中间件适用于整个 FastAPI 应用程序,通常用于执行全局操作,例如身份验证、日志记录、异常处理等。这使得您可以在整个应用程序中共享相同的中间件逻辑,而不需要为每个路由重复添加相同的中间件。

                                    此装饰器可以接受以下两个参数:

                                    • middleware_type(必需):字符串参数,用于指定中间件的类型。

                                      在 FastAPI 中,中间件可以分为以下两种类型:

                                      • “http”:HTTP 中间件

                                        这种中间件将在每个 HTTP 请求处理期间执行,适用于处理 HTTP 请求和响应的操作。

                                      • “websocket”:WebSocket 中间件

                                        这种中间件将在 WebSocket 连接的处理期间执行,适用于处理 WebSocket 请求和响应的操作。

                                      • priority(可选):整数参数,用于指定中间件的优先级。

                                        如果应用程序中有多个中间件,可以使用此参数来控制它们的执行顺序。

                                        较小的数字表示较高的优先级,中间件将按照优先级升序执行。

                                        如果不指定 priority 参数,中间件的默认优先级为 50。

                                        app = FastAPI()
                                        # 自定义中间件处理函数
                                        @app.middleware("http")
                                        async def log_requests(request: Request, call_next):
                                            logger.info(f"Incoming request: {request.method} {request.url}")
                                            response = await call_next(request)
                                            logger.info(f"Outgoing response: {response.status_code}")
                                            return response
                                        

                                        websocket():创建 WebSocket 路由

                                        • websocket() 函数:创建 WebSocket 路由,从而实现与客户端之间的实时双向通信。

                                          WebSocket 是一种在单个长连接上进行全双工通信的协议,适用于需要实时更新数据的应用场景,例如聊天应用、实时数据展示等。

                                          在客户端,可以使用浏览器内置的 WebSocket API 或其他 WebSocket 客户端库来与 FastAPI WebSocket 路由进行通信。

                                        • 代码示例:

                                          from fastapi import FastAPI, WebSocket
                                          app = FastAPI()
                                          # WebSocket 路由
                                          @app.websocket("/ws")
                                          async def websocket_endpoint(websocket: WebSocket):
                                              await websocket.accept()
                                              while True:
                                                  data = await websocket.receive_text()
                                                  await websocket.send_text(f"You said: {data}")
                                          
                                          • 使用 app.websocket() 方法创建了一个 /ws 的 WebSocket 路由。在 WebSocket 连接建立后,使用 await websocket.accept() 方法接受连接。
                                          • 然后,在一个无限循环中使用 await websocket.receive_text() 方法接收客户端发送的文本消息,并使用 await websocket.send_text() 方法将消息返回给客户端。

                                            mount():安装子应用程序(静态文件)

                                            • mount() 函数:用于将另一个 ASGI 应用程序安装为 FastAPI 应用程序的子应用程序。

                                              使用 mount 安装子应用程序可以方便的将多个应用程序组合在一起,实现更复杂的应用程序逻辑结构。例如,将多个 API 应用程序组装成一个网关应用程序,将多个应用程序组装成一个单页面应用程序等等。

                                              支持参数:

                                              • path :类型为字符串,必传参数,指定 url 访问的路径
                                              • app :类型为 ASGIApp,必传参数,挂载的是静态文件对象
                                                • directory :指定挂载的是静态文件目录
                                                • name :指定 fastapi 内部使用的名称。默认为 None
                                                • 访问静态文件方式:直接在浏览器输入 ip:端口/路径/文件全名.后缀 即可

                                                • 代码示例(配置静态文件路径):

                                                  import uvicorn
                                                  from fastapi import FastAPI
                                                  from fastapi.staticfiles import StaticFiles
                                                  app = FastAPI()
                                                  # 配置静态文件路径
                                                  app.mount("/static", StaticFiles(directory="static"), name="static")
                                                  uvicorn.run(app="main:app", host="0.0.0.0", port=8000, reload=True)