使用FastAPI操作DataFrame遇异常:无法向DataFrame添加行
问题解决步骤
错误原因
你遇到的UnboundLocalError是因为:在函数内部对df_marks执行赋值操作时,Python会自动将其判定为局部变量,但你在赋值语句df_marks = df_marks.append(...)里先引用了这个未定义的局部变量,从而触发报错。
同时代码还有几个潜在问题:
- 两个GET路由使用了同名的
get_index函数,会导致后定义的路由覆盖前一个 - pandas的
append方法已在2.0+版本中被弃用,建议改用pd.concat - PUT请求硬编码了新增数据,不符合接口设计逻辑,应该接收客户端传入的参数
具体修复方案
方案1:使用global声明全局变量(简单但不推荐多线程场景)
在需要修改全局df_marks的函数里,先声明global df_marks,明确告诉Python该变量是全局的:
import pandas as pd from fastapi import FastAPI from pydantic import BaseModel data = {'name': ['Somu', 'Kiku', 'Amol', 'Lini'], 'marks': ['A', "B", "C", "A"]} df_marks = pd.DataFrame(data) api = FastAPI(title='my_API') # 修复路由函数重名问题,改为get_single_data @api.get('/') def get_single_data(): return df_marks.iloc[1,1] @api.get('/test') def test_add_data(): global df_marks # 声明使用全局变量 # 注意保持列与原DataFrame一致,避免新增无意义列 new_line = pd.DataFrame({'name':['Jo'], 'marks':["A"]}) df_marks = pd.concat([df_marks, new_line], ignore_index=True) # 替换弃用的append return df_marks.iloc[1,1] # 定义请求体模型,接收客户端传来的数据 class MarkItem(BaseModel): name: str marks: str @api.put('/add') def add_user(item: MarkItem): global df_marks new_line = pd.DataFrame([item.dict()]) # 将Pydantic模型转为DataFrame行 df_marks = pd.concat([df_marks, new_line], ignore_index=True) return df_marks.iloc[1,1]
方案2:将DataFrame绑定到FastAPI实例(推荐,更符合Web应用规范)
把df_marks作为FastAPI实例的属性,避免全局变量的潜在线程安全问题:
import pandas as pd from fastapi import FastAPI from pydantic import BaseModel data = {'name': ['Somu', 'Kiku', 'Amol', 'Lini'], 'marks': ['A', "B", "C", "A"]} api = FastAPI(title='my_API') api.df_marks = pd.DataFrame(data) # 将DataFrame绑定到api实例 @api.get('/') def get_single_data(): return api.df_marks.iloc[1,1] @api.get('/test') def test_add_data(): new_line = pd.DataFrame({'name':['Jo'], 'marks':["A"]}) api.df_marks = pd.concat([api.df_marks, new_line], ignore_index=True) return api.df_marks.iloc[1,1] class MarkItem(BaseModel): name: str marks: str @api.put('/add') def add_user(item: MarkItem): new_line = pd.DataFrame([item.dict()]) api.df_marks = pd.concat([api.df_marks, new_line], ignore_index=True) return api.df_marks.iloc[1,1]
额外说明
- 你之前新增的行用了
physics列,但原DataFrame只有name和marks列,会导致新增无意义列,建议保持列一致,避免后续读取异常。 - FastAPI是多线程框架,如果是生产环境,直接修改内存中的DataFrame会有线程安全问题,建议使用数据库存储数据,而非内存中的DataFrame。
内容的提问来源于stack exchange,提问作者bum
相关产品推荐
相关产品推荐

