如果你熟悉 Java,第一次看到 FastAPI 可能会有点意外:启动一个 Web 服务,竟然只需要几行代码。
在 Java 里,我们经常会用 Spring Boot,需要创建项目、引入依赖、写启动类,再配置 Controller。
而 FastAPI 简单很多,几行 Python 代码就能启动一个接口。对于做接口开发、Mock 服务或者测试工具来说,这种轻量的开发方式还是非常舒服的。
这篇文章就从最简单的例子开始,带你一步一步认识 FastAPI。
它们干的事情其实差不多:
都是用来开发 Web 接口的。
只不过 Spring Boot 使用的是 Java,而 FastAPI 使用的是 Python。
如果你完全没有接触过 FastAPI,也没关系。这篇文章我们不着急上来就讲一堆概念,而是从最简单的一个接口开始,一点一点把 FastAPI 搞明白。
我们平时访问一个网站,或者前端调用后端接口,本质上都是在进行网络请求。
比如前端发送:
GET /user后端收到请求之后,查询数据库,然后返回:
{ "id": 1, "name": "张三"}整个过程可以简单理解成:
前端 ->发送HTTP请求 ->FastAPI ->行我们的代码 ->返回数据 ->前端所以你可以先把 FastAPI 理解成:
一个可以帮助我们快速编写 HTTP 接口的 Python 框架。
例如我们要写一个 /hello 接口。
使用 FastAPI,只需要:
from fastapi import FastAPI
app = FastAPI()
@app.get("/hello")
def hello():
return "Hello World"就这么几行。
启动之后,访问:
http://127.0.0.1:8000/hello就能看到:
"Hello World"是不是比想象中简单?
可能有人会问:
Python 本身不能启动 HTTP 服务吗?为什么还需要 FastAPI?
当然可以。
但是如果不用 Web 框架,我们需要自己处理很多东西:
HTTP请求->解析请求->判断GET还是POST->解析URL->解析参数->解析JSON->调用业务代码->组装HTTP响应这些事情自己处理起来会比较麻烦。
而 FastAPI 帮我们把这些事情都做好了。
我们只需要关心:
这个URL是什么?->请求来了以后做什么?->最后返回什么?这就是 Web 框架存在的意义。
安装 FastAPI:
pip install fastapi
还需要安装一个东西:
pip install "uvicorn[standard]"
这个 Uvicorn 是干什么的?
简单说:
FastAPI 负责我们的 Web 应用代码,Uvicorn 负责把这个 Web 应用真正跑起来。
可以把它们理解成:
客户端 -> Uvicorn -> FastAPI -> 我们的代码新建一个文件:
main.py然后写:
from fastapi import FastAPI
app = FastAPI()
@app.get("/hello")
def hello():
return "Hello World"现在我们一行一行看。
from fastapi import FastAPI这句话不用想得太复杂。
就是:
从 FastAPI 里面把
FastAPI这个东西拿过来使用。
app = FastAPI()这里创建了一个 FastAPI 应用。
后面我们所有的接口,基本都是挂在这个 app 上。
你可以简单理解:
app ->我们的整个Web应用下面这部分是第一次学习 FastAPI 时比较容易懵的地方:
@app.get("/hello")
def hello():
return "Hello World"其实不用想得太复杂。
它表达的意思就是:
如果有人通过 GET 请求访问
/hello,就执行下面的hello()方法。
所以:
@app.get("/hello")相当于告诉 FastAPI:
GET /hello ->hello()然后:
def hello():就是具体要执行的代码。
最后:
return "Hello World"就是把结果返回给客户端。
整个过程:
客户端 ->GET /hello ->FastAPI找到/hello ->执行hello() ->返回Hello World这样是不是就容易理解了?
代码写好了,接下来要让它跑起来。
在 main.py 所在目录执行:
uvicorn main:app --host 0.0.0.0 --port 8000
第一次看到:
main:app可能会有点懵。
其实非常简单。
我们刚才的文件叫:
main.py里面有:
app = FastAPI()所以:
main:app就是:
main.py ->app告诉 Uvicorn:
去
main.py里面找到app这个 FastAPI 对象,然后把它启动起来。
启动成功之后,可以打开浏览器:
http://127.0.0.1:8000/hello如果一切正常,就会看到:
"Hello World"恭喜。
到这里,你已经成功写出了第一个 FastAPI 接口。
到这里就有人问了,为什么会带双引号返回,因为fastapi会把它当作一个json字符串,所以会带双引号,如果不带则需要加些内容,像下面这样,为了方便调试,发送端我这边用的是postman。
from fastapi import FastAPIfrom fastapi.responses import PlainTextResponse
app = FastAPI()
@app.get("/hello",response_class=PlainTextResponse)
def hello():
return "Hello World"
实际开发中,我们很少只返回:
Hello World更多时候返回的是 JSON。
比如:
{ "id": 1, "name": "张三", "age": 20}FastAPI 写起来也很简单。
@app.get("/user")
def get_user():
return { "id": 1, "name": "张三", "age": 20 }访问:
GET /user就可以得到:
{ "id": 1, "name": "张三", "age": 20}
这里有个很方便的地方:
我们返回的是 Python 的字典:
{ "id": 1, "name": "张三", "age": 20}FastAPI 会帮我们转换成 JSON。
所以我们不需要自己手动拼 JSON 字符串。
假设我们现在有一个查询用户的接口。
我们希望:
/user?id=100然后根据这个 id 查询用户。
可以这样写:
@app.get("/user1")
def get_user(id: int):
return { "id": id, "name": "张三" }这里:
id: int是什么意思?
可以理解成:
我希望客户端传过来的
id是一个整数。
那么访问:
/user?id=100FastAPI 就会把:
100传给:
id最终返回:

{ "id": 100, "name": "张三"}比如我们访问:
/user?id=abc但是代码要求:
id: int也就是说:
id必须是整数而:
abc显然不是整数。
这时候 FastAPI 会帮我们进行参数校验,并返回错误信息。

这就是 FastAPI 很方便的一个地方:
很多参数校验工作,不需要我们自己一个个写。
刚才我们写的是:
/user?id=100这个 id 是查询参数。
还有一种常见写法:
/user/100这时候可以写:
@app.get("/user/{id}")
def get_user(id: int):
return { "id": id }这里:
/user/{id}中的 {id} 就是一个路径参数。
访问:
/user/100
FastAPI 会自动把:
100传给:
id这两个刚开始很容易搞混。
/user?id=100代码:
@app.get("/user")
def get_user(id: int):
.../user/100代码:
@app.get("/user/{id}")
def get_user(id: int):
...简单记:
/user?id=100 -> Query /user/100 -> Path实际项目中两种方式都会大量使用。
GET 通常用来查询数据。
如果我们要创建数据,经常会使用 POST。
例如:
@app.post("/user")
def create_user():
return { "code": 0, "message": "创建成功" }这时候:
POST /user就会进入:
create_user()假设客户端发送:
{ "name": "张三", "age": 20}我们可以先定义一个数据模型:
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int然后接口这样写:
@app.post("/user")
def create_user(user: User):
return { "name": user.name, "age": user.age }客户端发送:
POST /userContent-Type: application/json请求体:
{ "name": "张三", "age": 20}
FastAPI 会自动帮我们做这些事情:
JSON请求 ->解析JSON ->创建User对象 ->检查参数 ->调用create_user()所以我们在方法里面直接使用:
user.nameuser.age就可以了。
刚才出现了:
from pydantic import BaseModel这个 Pydantic 是 FastAPI 中非常重要的一部分。
它主要负责:
数据模型和数据校验。
例如:
class User(BaseModel):
name: str
age: int实际上就是在告诉程序:
name:字符串 age:整数这样请求数据的结构就非常清楚。
比如:
{ "name": "张三", "age": 20}是正常的。
如果:
{ "name": "张三", "age": "abc"}那么就会触发校验。

代码写完以后,我们通常还需要接口文档。
如果使用 FastAPI,很多情况下根本不需要自己单独写。
启动服务之后访问:
http://127.0.0.1:8000/docs就可以看到自动生成的接口文档。
例如:
GET /helloGET /userPOST /user点击接口之后,还可以直接调试。
例如:
Try it out然后输入参数:
id = 100点击执行,就可以直接调用接口。

这对于开发来说非常方便。
FastAPI 还有一个很重要的特点:
支持异步编程。
例如普通写法:
@app.get("/test")
def test():
return { "message": "success" }也可以写成:
@app.get("/test")
async def test():
return { "message": "success" }这里多出来的:
async表示这是一个异步函数。
如果里面需要等待一个异步操作,可以使用:
await例如:
import asynciofrom fastapi import FastAPI
app = FastAPI()
@app.get("/test")
async def test():
await asyncio.sleep(1)
return { "message": "success" }这里模拟等待 1 秒。
假设服务器同时收到两个请求。
第一个请求需要等待 5 秒:
请求A ->等待5秒第二个请求马上就能完成:
请求B ->马上返回如果程序大量时间都在等待网络、数据库或者其他服务,那么异步就可以让程序在等待期间去处理其他任务。
例如:
请求A ->等待数据库 -> 请求B -> 返回 ->请求A继续 ->返回所以异步特别适合:
这些需要等待的场景。
不过这里一定要注意:
不是把
def改成async def,程序性能就一定提高。
如果你的代码主要是在做 CPU 计算,那么异步并不能自动解决 CPU 性能问题。
前面一直提到 Uvicorn。
现在可以把它们的关系简单理解成:
HTTP请求 -> Uvicorn -> FastAPI -> 我们的代码 -> 返回结果FastAPI 是:
Web应用框架。
Uvicorn 是:
运行 FastAPI 应用的 ASGI 服务器。
所以它们是两个不同的东西。
如果是第一次学习 FastAPI,不要一开始就去研究高并发、异步、部署这些东西。
先把最基本的几个概念搞清楚:
请求 ->路由 ->参数 ->执行方法 ->返回结果等这套流程理解之后,再往后学习,会容易很多。
FastAPI 可以简单理解成:
一个让我们使用 Python 快速开发 HTTP API 的 Web 框架。
最基本的 FastAPI 程序其实非常简单。
而 FastAPI 真正方便的地方在于,它不只是能简单地返回数据,还帮我们解决了很多开发 API 时经常遇到的问题:
路由
参数解析
参数校验
JSON
Pydantic
异常处理
API文档
异步
WebSocket所以如果你刚开始接触 Python Web 开发,完全可以先从一个最简单的 /hello 接口开始。
不要一上来就背概念。
先把代码跑起来,然后慢慢理解:
“我发送一个 HTTP 请求,FastAPI 到底是怎么找到我的方法,又是怎么把参数传给我的?”
把这个过程真正搞懂,后面的内容就会越来越容易。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。