网易首页 > 网易号 > 正文 申请入驻

三分钟了解 Python3 的异步 Web 框架 FastAPI

0
分享至

  快速编码,功能完善。从启动到部署,实例详解异步 py3 框架选择 FastAPI 的原因。

  FastAPI 介绍

  FastAPI 与其它 Python-Web 框架的区别

  在 FastAPI 之前,Python 的 Web 框架使用的是 django、flask、tornado 三种 Web 框架。

  django 自带 admin,可快速构建,但是比较笨重。如果是 mvc 形式的开发,很多已经封装好了,的确蛮合适。但如果是 restful 风格设计,则 django 就显得有一些笨重了。

  flask 快速构建,自由度高。因为它十分轻盈,插件即插即用,很适合用来做 restful 风格的设计

  tornado Python Web 框架和异步网络库,它执行非阻塞 I/O ,没有对 REST API 的内置支持,但是用户可以手动实现。

  FastAPI 快速构建,异步 IO,自带 Swagger 作为 API 文档,不用后续去内嵌 Swagger-Ui

  我个人认为 FastAPI 是一个专门为 restful 风格设计,全面服务于 API 形式的 Web 后端框架。

  FastAPI 官方定位

  在 FastAPI 官方文档中,可以看到官方对 FastAPI 的定位:

  快速:非常高的性能,向 NodeJS 和 go 看齐(感谢 Starlette 和 Pydantic)

  快速编码:将功能开发速度提高约 200% 至 300%。

  错误更少:减少约 40% 的人为错误(开发人员)。* (FastAPI 内置很多 Python 高版本的语法,比如类型注释,typing 库等等,因此被要求的 Python 版本为 3.6+)

  简易:旨在易于使用和学习。减少阅读文档的时间。

  功能完善: 自带 Swagger 作为 API 文档

  Framework Benchmarks

  https://www.techempower.com/benchmarks/#section=data-r19&hw=ph&test=fortune

  上图可以看出,在高并发下 4 个框架的排名情况。单纯从性能出发,Web 框架是排在第一的。在选用框架的时候,性能是一方面,我们还要看业务上的需求和使用场景,最适合的才是最好的。

  下面简单介绍一下 FastAPI 的一些用法和特性.

  启动FastAPI

  # pip install fastapi# pip install uvicornfrom fastapi import FastAPIapp = FastAPI()@app.get("/")def read_root():return {"Hello": "World"}@app.get("/items/{item_id}")def read_item(item_id: int, q: str = None):return {"item_id": item_id, "q": q}# uvicorn main:app # 启动# uvicorn main:app --reload # 支持热更新# uvicorn main:app --host 0.0.0.0 --port 8889 --reload # 自定义IP+端口

  FastAPI 支持异步请求

  from fastapi import FastAPIapp = FastAPI()@app.get("/")async def read_root():return {"Hello": "World"}
@app.get("/items/{item_id}")async def read_item(item_id: int, q: str = None):return {"item_id": item_id, "q": q}

  对 API 接口的支持性优异

  设置根目录

  # main.pyfrom fastapi import FastAPIimport usersapp = FastAPI()app.include_router(users.router,prefix="/fastapi/play/v1/users", # 路由前缀tags=['users'] # 路由接口类别)# routers/users.pyfrom fastapi import FastAPI,APIRouterfrom datetime import datetime,timedeltarouter = APIRouter()@router.get("/get/users/")async def get_users():return {"desc":"Return to user list"}

  对路径参数进行限制

  # 根据名字获取列表@router.get("/get/user/{username}")async def get_user_by_username(username :str):"""- username: 用户名"""return {"desc":"this username is "+ username}

  对查询参数做限制

  @router.get("/friends/")
# 设置为None的时候,默认不可以不填async def get_friends_by_id(id :int=None):for item in test_json['friends']:if item['id'] == id:return itemelse:return {"desc": "no this id"}# 多参数请求查询from typing import List@router.get("/items/")async def read_items(q: List[str] = Query(["foo", "bar"])):query_items = {"q": q}return query_items

  设置请求体

  # 设置请求实体from pydantic import BaseModel,Fieldclass requestModel(BaseModel):name :strage : int = Field(..., gt=0, description="The age must be greater than zero")desc: str

@router.post("/post/UserInfo/")async def post_UserInfo(item: requestModel):return item

  请求体嵌套

  from pydantic import BaseModel,Fieldclass levelInfoModel(BaseModel):id:int = Noneinfo: str = None
class ClassInfo(BaseModel):id: int = Nonename: str = Field(..., max_length=20, min_length=10,description="The necessary fields")desc: str = Field(None, max_length=30, min_length=10)levelInfo: List[levelInfoModel]
class Config:schema_extra = {"example": {"id": 1,"name": "Foo","desc": "A very nice Item","levelInfo": [{"id": 1,"info": "一级"}]}}
@router.post("/info/")async def get_classInfo(item:ClassInfo):return item

  自定义响应码

  @router.post("/items/", status_code=201)async def create_item(name: str):return {"name": name}
from fastapi import FastAPI, status

@app.post("/items/", status_code=status.HTTP_201_CREATED)async def create_item(name: str):return {"name": name}

  依赖注入

  from fastapi import Depends, FastAPI
async def common_parameters(q: str = None, skip: int = 0, limit: int = 100):return {"q": q, "skip": skip, "limit": limit}
@router.get("/items/")async def read_items(commons: dict = Depends(common_parameters)):return commons
@router.get("/users/")async def read_users(commons: dict = Depends(common_parameters)):return commons

  FastAPI 框架支持多层嵌套依赖注入

  登录demo

  # 安装环境mkdir fastapi-demo && cd fastapi-demovirtualenv envsource env/bin/activate
# 下载项目git clone https://github.com/hzjsea/BaseFastapicd BaseFastapi/pip install -r requirements.txt# 开启项目uvicorn main:app --reload# uvicorn main:app --host 0.0.0.0 --port 80 --reload

  总结

  FastAPI 的设计还是很符合 restful 的,在用到很多新技术的同时,也没有抛弃之前一些比较好用的内容,包括类型注释、依赖注入,Websocket,swaggerui 等等,以及其他的一些注释,比如 GraphQL。数据库以及 orm 的选择

  sqlalchemy 但是不支持异步,不过貌似可以扩展成异步。

  tortoise-orm 类 django-orm 的异步 orm,不过正在起步过程中,有些功能还没有完成。

  sqlalchemy实例

  from typing import Listimport databasesimport sqlalchemyfrom fastapi import FastAPIfrom pydantic import BaseModel# SQLAlchemy specific code, as with any other appDATABASE_URL = "sqlite:///./test.db"# DATABASE_URL = "postgresql://user:password@postgresserver/db"database = databases.Database(DATABASE_URL)metadata = sqlalchemy.MetaData()notes = sqlalchemy.Table("notes",metadata,sqlalchemy.Column("id", sqlalchemy.Integer, primary_key=True),sqlalchemy.Column("text", sqlalchemy.String),sqlalchemy.Column("completed", sqlalchemy.Boolean),)engine = sqlalchemy.create_engine(DATABASE_URL, connect_args={"check_same_thread": False})metadata.create_all(engine)

class NoteIn(BaseModel):text: strcompleted: bool

class Note(BaseModel):id: inttext: strcompleted: bool

app = FastAPI()

@app.on_event("startup")async def startup():await database.connect()

@app.on_event("shutdown")async def shutdown():await database.disconnect()

@app.get("/notes/", response_model=List[Note])async def read_notes():query = notes.select()return await database.fetch_all(query)

@app.post("/notes/", response_model=Note)async def create_note(note: NoteIn):query = notes.insert().values(text=note.text, completed=note.completed)last_record_id = await database.execute(query)return {**note.dict(), "id": last_record_id}

  tortoise-orm实例

  # main.pyfrom tortoise.contrib.fastapi import HTTPNotFoundError, register_tortois# 创建的数据表models = ["app.Users.models","app.Face.models","app.Roster.models","app.Statistical.models","app.pay.models"]
register_tortoise(app,db_url="mysql://username:password@ip:port/yydb",modules={"models": models},generate_schemas=True,add_exception_handlers=True,)
# models.pyfrom tortoise import fields,modelsfrom tortoise.contrib.pydantic import pydantic_queryset_creatorfrom pydantic import BaseModelclass RosterGroupTable(models.Model):id = fields.IntField(pk=True)phone = fields.CharField(max_length=20,blank=True,null=True)name = fields.CharField(max_length=20)
class Meta:db = "RosterGroupTable"
class RosterTabel(models.Model):id = fields.IntField(pk=True)phone = fields.CharField(max_length=20,blank=True,null=True)name = fields.CharField(max_length=20)group_id = fields.ForeignKeyField(model_name='models.RosterGroupTable',on_delete=fields.CASCADE,related_name="events",blank=True,null=True)
class Meta:db = "RosterTabel"
RosterGroupTable_desc = pydantic_queryset_creator(RosterGroupTable)RosterTabel_desc = pydantic_queryset_creator(RosterTabel)


# roster.py@router.post("/roster_statistics/add")async def roster_add_statics(*,item:RosterItem,token :str):res = await RosterTabel.filter(id=item['memberId']).first()if res:await StatisticalRosterTable.create(phone = current_user.Phone,date = item['date'],time = item['time'],data = item['data'],name_id_id = item['memberId'],temp_type = item['tm_type'],today_num = item['todayNum'],group_id_id = res.group_id_id,name = res.name)else:return rp_faildMessage(msg="名单不存在",code=-1)return rp_successMessage(msg="名单创建成功",code=0)

  部署

  dockerfile

  #================================================================================# 基于Python3.7的创建fastapi的dockerfile文件# fastapi + Python3.7 + guvicorn#================================================================================
FROM Python:3.7LABEL version="v1" \description="fastapi" \maintainer="hzjsea" \using="fastapi & Python3.7 office image & gunicorn"WORKDIR /root/codeCOPY . .RUN pip install -r requirements.txtEXPOSE 8889CMD ["gunicorn","-c","guvicorn.conf","main:app"]

  supervisor项目托管

  [program:webserver]directory=/root/hzj/fastapi_playcommand=/root/hzj/pro_env_all/venv/bin/uvicorn main:app --host 0.0.0.0 --port 8888autostart = true

  部署完整示例

  FastAPI官方提供了一个前后端分离项目完整示例

  https://github.com/tiangolo/full-stack-fastapi-postgresql

  文档及项目地址:

  Documentation: https://fastapi.tiangolo.com

  快 来小 拍

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
安徽省公安厅公布4起黑恶犯罪典型案例

安徽省公安厅公布4起黑恶犯罪典型案例

人民资讯
2026-05-15 15:33:32
刘亦菲越来越喜欢穿丝袜了

刘亦菲越来越喜欢穿丝袜了

乡野小珥
2026-05-15 15:51:07
入朝前夕,毛主席听取林帅建议:换掉13兵团主将!两年后才知高明

入朝前夕,毛主席听取林帅建议:换掉13兵团主将!两年后才知高明

搜史君
2026-05-08 13:00:16
我64岁,退休金8500存款20万,血的教训告诉我,不要跟谁再续前缘

我64岁,退休金8500存款20万,血的教训告诉我,不要跟谁再续前缘

宅家伍菇凉
2024-08-09 15:00:02
美国诺格六代机曝光:全向隐身锁定50年制海权

美国诺格六代机曝光:全向隐身锁定50年制海权

暗香暗香
2026-05-15 08:23:08
宋佳调侃张嘉益:为何不推荐我试镜《主角》? 张嘉益回复全场笑翻

宋佳调侃张嘉益:为何不推荐我试镜《主角》? 张嘉益回复全场笑翻

观察鉴娱
2026-05-15 13:33:47
莫名其妙!世界银行前行长竟要求中国,“不许囤积化肥和粮食”

莫名其妙!世界银行前行长竟要求中国,“不许囤积化肥和粮食”

解锁世界风云
2026-05-15 16:43:31
相亲要1000万彩礼的“泡面姐姐”露真容,网友很失望劝她戴上面罩

相亲要1000万彩礼的“泡面姐姐”露真容,网友很失望劝她戴上面罩

汉史趣闻
2026-05-13 10:21:50
这一夜北京机场爆火!红裙女孩一递花,这献花姑娘把东方美演活了

这一夜北京机场爆火!红裙女孩一递花,这献花姑娘把东方美演活了

乐悠悠娱乐
2026-05-15 10:28:57
美记:太阳可能先签后换交易掉马克-威廉姆斯,扶正马鲁阿奇

美记:太阳可能先签后换交易掉马克-威廉姆斯,扶正马鲁阿奇

懂球帝
2026-05-15 09:42:34
陪玩陪睡根本不够!认干爹、舔手指,背地里的阴暗面完全藏不住了

陪玩陪睡根本不够!认干爹、舔手指,背地里的阴暗面完全藏不住了

杰丝聊古今
2026-05-03 13:35:27
美陆军部长承认大幅落后乌克兰!连续修改规则,瑞典军队仍被击败

美陆军部长承认大幅落后乌克兰!连续修改规则,瑞典军队仍被击败

鹰眼Defence
2026-05-15 16:48:06
时隔九年,特朗普再访华:2017年他带走了2535亿美元大单,2026年他能带走什么?

时隔九年,特朗普再访华:2017年他带走了2535亿美元大单,2026年他能带走什么?

昨日Mirror
2026-05-15 10:06:56
如今已经不是房价跌不跌的问题了,而是新房正在“摧毁”二手房

如今已经不是房价跌不跌的问题了,而是新房正在“摧毁”二手房

蜉蝣说
2026-05-14 18:33:50
35岁女子去做私处紧缩,缝针断在肉里,医生徒手掏了半小时没找着

35岁女子去做私处紧缩,缝针断在肉里,医生徒手掏了半小时没找着

离离言几许
2026-04-21 19:53:18
老公向舅舅借120万做生意,三年后盈利了,舅舅说:给利息

老公向舅舅借120万做生意,三年后盈利了,舅舅说:给利息

游戏收藏指南
2026-05-15 17:07:27
恩里克:刚来就拿两座冠军?我连一个都没想过,更别说两个了

恩里克:刚来就拿两座冠军?我连一个都没想过,更别说两个了

懂球帝
2026-05-15 04:23:43
特朗普很开心,不仅致辞祝酒,还多次“畅饮”

特朗普很开心,不仅致辞祝酒,还多次“畅饮”

三叔的装备空间
2026-05-14 22:35:18
伊朗也有司马南:荧幕上骂美国是“大撒旦”,私下拿绿卡喝星巴克

伊朗也有司马南:荧幕上骂美国是“大撒旦”,私下拿绿卡喝星巴克

壹家言
2026-04-17 10:43:11
央视以1.1亿拿下世界杯版权,赚了还是赔了?

央视以1.1亿拿下世界杯版权,赚了还是赔了?

雨秋闲话
2026-05-15 15:41:49
2026-05-15 17:43:00
又拍云
又拍云
一站式的云加速服务
671文章数 54关注度
往期回顾 全部

科技要闻

两年联姻一地鸡毛,传苹果OpenAI濒临决裂

头条要闻

白宫称中方同意重开霍尔木兹海峡 外交部回应

头条要闻

白宫称中方同意重开霍尔木兹海峡 外交部回应

体育要闻

德约科维奇买的球队,从第6级联赛升入法甲

娱乐要闻

方媛为何要来《桃花坞6》没苦硬吃?

财经要闻

特朗普的北京时刻

汽车要闻

标杆级乘坐感受 驾驶智界V9需要再细腻一点?

态度原创

时尚
家居
旅游
亲子
教育

56岁逆风翻盘,她怎么从全网群嘲变成了大家的天才女友?

家居要闻

110㎡淡而有致的生活表达

旅游要闻

容贤标:推动猫儿山向全国性山海经文化高地跃升

亲子要闻

东城发布2026年幼儿园招生公告

教育要闻

既要学校稳,又要同学好,还要门槛低?这所学校满足你!

无障碍浏览 进入关怀版