使用Python FastAPI构建Web服务的实现


Posted in Python onJune 08, 2020

FastAPI 是一个使用 Python 编写的 Web 框架,还应用了 Python asyncio 库中最新的优化。本文将会介绍如何搭建基于容器的开发环境,还会展示如何使用 FastAPI 实现一个小型 Web 服务。

起步

我们将使用 Fedora 作为基础镜像来搭建开发环境,并使用 Dockerfile 为镜像注入 FastAPI、Uvicorn 和 aiofiles 这几个包。

FROM fedora:32
RUN dnf install -y python-pip \
  && dnf clean all \
  && pip install fastapi uvicorn aiofiles
WORKDIR /srv
CMD ["uvicorn", "main:app", "--reload"]

在工作目录下保存 Dockerfile 之后,执行 podman 命令构建容器镜像。

$ podman build -t fastapi .
$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/fastapi latest 01e974cabe8b 18 seconds ago 326 MB

下面我们可以开始创建一个简单的 FastAPI 应用程序,并通过容器镜像运行。

from fastapi import FastAPI
 
app = FastAPI()
 
@app.get("/")
async def root():
  return {"message": "Hello Fedora Magazine!"}

将上面的代码保存到 main.py 文件中,然后执行以下命令开始运行:

$ podman run --rm -v $PWD:/srv:z -p 8000:8000 --name fastapi -d fastapi
$ curl http://127.0.0.1:8000
{"message":"Hello Fedora Magazine!"

这样,一个基于 FastAPI 的 Web 服务就跑起来了。由于指定了 --reload 参数,一旦 main.py 文件发生了改变,整个应用都会自动重新加载。你可以尝试将返回信息 "Hello Fedora Magazine!" 修改为其它内容,然后观察效果。

可以使用以下命令停止应用程序:

$ podman stop fastapi

构建一个小型 Web 服务

接下来我们会构建一个需要 I/O 操作的应用程序,通过这个应用程序,我们可以看到 FastAPI 自身的特点,以及它在性能上有什么优势(可以在这里参考 FastAPI 和其它 Python Web 框架的对比)。为简单起见,我们直接使用 dnf history 命令的输出来作为这个应用程序使用的数据。

首先将 dnf history 命令的输出保存到文件。

$ dnf history | tail --lines=+3 > history.txt

在上面的命令中,我们使用 tail 去除了 dnf history 输出内容中无用的表头信息。剩余的每一条 dnf 事务都包括了以下信息:

  • id:事务编号(每次运行一条新事务时该编号都会递增)
  • command:事务中运行的 dnf 命令
  • date:执行事务的日期和时间

然后修改 main.py 文件将相关的数据结构添加进去。

from fastapi import FastAPI
from pydantic import BaseModel
 
app = FastAPI()
 
class DnfTransaction(BaseModel):
  id: int
  command: str
  date: str

FastAPI 自带的 pydantic 库让你可以轻松定义一个数据类,其中的类型注释对数据的验证也提供了方便。

再增加一个函数,用于从 history.txt 文件中读取数据。

import aiofiles
 
from fastapi import FastAPI
from pydantic import BaseModel
 
app = FastAPI()
 
class DnfTransaction(BaseModel):
  id: int
  command: str
  date: str
 
 
async def read_history():
  transactions = []
  async with aiofiles.open("history.txt") as f:
    async for line in f:
      transactions.append(DnfTransaction(
        id=line.split("|")[0].strip(" "),
        command=line.split("|")[1].strip(" "),
        date=line.split("|")[2].strip(" ")))
  return transactions

这个函数中使用了 aiofiles 库,这个库提供了一个异步 API 来处理 Python 中的文件,因此打开文件或读取文件的时候不会阻塞其它对服务器的请求。

最后,修改 root 函数,让它返回事务列表中的数据。

@app.get("/")
async def read_root():
  return await read_history()

执行以下命令就可以看到应用程序的输出内容了。

$ curl http://127.0.0.1:8000 | python -m json.tool
[
{
"id": 103,
"command": "update",
"date": "2020-05-25 08:35"
},
{
"id": 102,
"command": "update",
"date": "2020-05-23 15:46"
},
{
"id": 101,
"command": "update",
"date": "2020-05-22 11:32"
},
....
]

总结

FastAPI 提供了一种使用 asyncio 构建 Web 服务的简单方法,因此它在 Python Web 框架的生态中日趋流行。要了解 FastAPI 的更多信息,欢迎查阅 FastAPI 文档。

本文中的代码可以在 GitHub 上找到。

到此这篇关于使用Python FastAPI构建Web服务的实现的文章就介绍到这了,更多相关Python FastAPI构建Web服务内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木! 

Python 相关文章推荐
django 自定义用户user模型的三种方法
Nov 18 Python
Python导入txt数据到mysql的方法
Apr 08 Python
Python使用pickle模块存储数据报错解决示例代码
Jan 26 Python
python 反向输出字符串的方法
Jul 16 Python
python 计算一个字符串中所有数字的和实例
Jun 11 Python
Python函数中参数是传递值还是引用详解
Jul 02 Python
pytorch中的transforms模块实例详解
Dec 31 Python
django执行数据库查询之后实现返回的结果集转json
Mar 31 Python
Python DataFrame使用drop_duplicates()函数去重(保留重复值,取重复值)
Jul 20 Python
2020版Python学习路线图(附学习资料)
Sep 15 Python
Python机器学习实战之k-近邻算法的实现
Nov 27 Python
Python批量解压&压缩文件夹的示例代码
Apr 04 Python
python爬虫把url链接编码成gbk2312格式过程解析
Jun 08 #Python
给ubuntu18安装python3.7的详细教程
Jun 08 #Python
Python 实现将numpy中的nan和inf,nan替换成对应的均值
Jun 08 #Python
使用Numpy对特征中的异常值进行替换及条件替换方式
Jun 08 #Python
Python替换NumPy数组中大于某个值的所有元素实例
Jun 08 #Python
python如何编写win程序
Jun 08 #Python
如何写python的配置文件
Jun 07 #Python
You might like
php制作中间带自己定义图片二维码的方法
2014/01/27 PHP
php fseek函数读取大文件两种方法
2016/10/12 PHP
[原创]php集成安装包wampserver修改密码后phpmyadmin无法登陆的解决方法
2016/11/23 PHP
php基于dom实现的图书xml格式数据示例
2017/02/03 PHP
Laravel使用消息队列需要注意的一些问题
2017/12/13 PHP
异步加载script的代码
2011/01/12 Javascript
jquery随意添加移除html的实现代码
2011/06/21 Javascript
javascripit实现密码强度检测代码分享
2013/12/12 Javascript
解决jquery操作checkbox火狐下第二次无法勾选问题
2014/02/10 Javascript
js弹出div并显示遮罩层
2014/02/12 Javascript
JavaScript实现找出数组中最长的连续数字序列
2014/09/03 Javascript
探讨JavaScript中的Rest参数和参数默认值
2015/07/29 Javascript
Nodejs express框架一个工程中同时使用ejs模版和jade模版
2015/12/28 NodeJs
JS实现简单的二维矩阵乘积运算
2016/01/26 Javascript
JS获取当前脚本文件的绝对路径
2016/03/02 Javascript
浅析$(function) ready和onload 的区别
2016/09/03 Javascript
jquery 动态增加,减少input表单的简单方法(必看)
2016/10/12 Javascript
微信小程序 登陆流程详细介绍
2017/01/17 Javascript
微信小程序 两种为对象属性赋值的方式详解
2017/02/23 Javascript
jQuery用noConflict代替$的实现方法
2017/04/12 jQuery
ionic实现底部分享功能
2017/05/11 Javascript
深入理解JavaScript的值传递和引用传递
2018/10/24 Javascript
一些可能会用到的Node.js面试题
2019/06/15 Javascript
layui 表单标签的校验方法
2019/09/04 Javascript
Vue解析带html标签的字符串为dom的实例
2019/11/13 Javascript
vscode自定义vue模板的实现
2021/01/27 Vue.js
[04:22]DSPL第二期精彩集锦:残血反杀!
2014/12/10 DOTA
[56:42]VP vs RNG 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
python笔记:mysql、redis操作方法
2017/06/28 Python
python使用mysql的两种使用方式
2018/03/07 Python
了解不常见但是实用的Python技巧
2019/05/23 Python
中国最大隐形眼镜网上商城:视客眼镜网
2016/10/30 全球购物
ETO男装官方网店:ETO Jeans
2019/02/28 全球购物
学习三严三实对照检查材料思想汇报
2014/09/22 职场文书
团员年度个人总结
2015/02/26 职场文书
评估“风险”创业计划的几大要点
2019/08/12 职场文书