FastAPI对接MongoDB启动报TypeError: %d格式需数字而非字符串
问题背景
我是Python初学者,正尝试开发一个从MongoDB数据库拉取数据的简易Web服务器,运行过程中遇到报错无法解决。
项目文件架构如下:
项目原始代码
# Database CONNECTION_URL = os.environ['mongoConnectionURL'] DATABASE_NAME = os.environ['mongoDatabaseName'] NEWS_COLLECTION = os.environ['mongodbNewsCollection'] app = FastAPI() # TODO JS has next function i'm currently unaware of app.add_middleware( CORSMiddleware, allow_origins=['*'], allow_headers=["Origin, X-Requested-With, Content-Type, Accept"], ) @app.get('/') def index(): return 'See /entries' @app.get('/entries') def getEntries(): client = MongoClient(CONNECTION_URL) databaseMongo = client.get_database(DATABASE_NAME) collectionMongo = databaseMongo.get_collection(NEWS_COLLECTION) result = list(collectionMongo.find()) for entry in result: return { 'data': result } if __name__ == "__main__": uvicorn.run(app, port=os.environ['PORT'])
报错信息
运行时抛出的错误栈如下:
Traceback (most recent call last): File "/usr/local/lib/python3.9/logging/__init__.py", line 1083, in emit msg = self.format(record) File "/usr/local/lib/python3.9/logging/__init__.py", line 927, in format return fmt.format(record) File "/usr/local/lib/python3.9/logging/__init__.py", line 663, in format record.message = record.getMessage() File "/usr/local/lib/python3.9/logging/__init__.py", line 367, in getMessage msg = msg % self.args TypeError: %d format: a number is required, not str
完整错误日志截图:
报错原因与解决方案
核心报错原因
抛出该错误的直接原因是传入uvicorn的port参数类型错误:
os.environ读取到的所有环境变量值默认都是字符串类型- uvicorn内部启动日志打印监听端口时,使用了
%d数字类型占位符格式化端口值,当拿到字符串类型的端口值时就会触发这个类型错误。
代码存在的其他问题
原始代码除了端口类型错误外,还有几处会影响运行的问题:
- 缺少必要的模块导入语句,直接运行会触发
NameError - CORS中间件的
allow_headers配置格式错误,要求传入列表类型,原代码把所有请求头拼接成了单个字符串 /entries接口中存在无意义的for循环:遍历查询结果时第一次循环就直接return,循环逻辑完全多余- 每次接口请求都新建MongoDB客户端连接,会造成不必要的资源开销,高并发场景下会拖慢服务性能
- MongoDB查询结果默认会携带
_id字段(ObjectId类型),FastAPI默认无法序列化该类型,会触发后续的序列化报错
修正后可运行代码
import os import uvicorn from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from pymongo import MongoClient # 读取数据库配置环境变量 CONNECTION_URL = os.environ['mongoConnectionURL'] DATABASE_NAME = os.environ['mongoDatabaseName'] NEWS_COLLECTION = os.environ['mongodbNewsCollection'] app = FastAPI() # 修正CORS中间件配置 app.add_middleware( CORSMiddleware, allow_origins=['*'], allow_headers=["*"], allow_methods=["*"] ) # 全局初始化MongoDB连接,避免重复创建客户端 client = MongoClient(CONNECTION_URL) db = client[DATABASE_NAME] news_collection = db[NEWS_COLLECTION] @app.get('/') def index(): return 'See /entries' @app.get('/entries') def get_entries(): # 查询时排除_id字段,避免序列化报错 result = list(news_collection.find({}, {"_id": 0})) return {"data": result} if __name__ == "__main__": # 关键修正:将字符串类型的端口值转为整数 uvicorn.run(app, port=int(os.environ['PORT']))
运行前检查项
- 提前安装依赖:执行命令
pip install fastapi uvicorn pymongo - 确认所有需要的环境变量都已正确配置:
mongoConnectionURL、mongoDatabaseName、mongodbNewsCollection、PORT - 本地测试时可以直接在代码里写死配置验证逻辑,确认无问题后再切换为环境变量读取方式
内容的提问来源于stack exchange,提问作者cyruslk
相关产品推荐
相关产品推荐

