如何在FastAPI中上传CSV文件并将其转换为Pandas Dataframe?

5hcedyr0  于 2023-04-27  发布在  其他
关注(0)|答案(1)|浏览(152)

我想上传一个文件到FastAPI后端,并将其转换为Pandas DataFrame。但是,我似乎不明白如何使用FastAPI的UploadFile对象来完成这一任务。更具体地说,我应该向pd.read_csv()函数传递什么?
以下是我的FastAPI端点:

@app.post("/upload")
async def upload_file(file: UploadFile):
    df = pd.read_csv("")
    print(df)
    return {"filename": file.filename}
omtl5h9j

omtl5h9j1#

下面给出了如何将上传到FastAPI的文件转换为Pandas DataFrame的各种选项。如果您还想将DataFrame转换为JSON并返回给客户端,请查看this answer。如果您想使用async def端点而不是def,请查看this answer如何以async方式读取文件内容,以及this answer来理解使用defasync def之间的区别。(在下面的示例中)在try-except-finally块中(如herehere所示),以便您可以捕获/引发任何可能的异常,并正确地closefile,以便从内存中释放对象并避免潜在的错误。
关于如何上传和读取CSV文件的相关答案可以在here(使用Jinja 2模板提供示例),以及here(将上传的CSV文件转换为JSON并返回给客户端)和here(提供不使用外部库的解决方案)中找到。

选项一

由于pandas.read_csv()可以接受file-like对象,因此您可以直接传递UploadFilefile-like对象。UploadFile公开了一个实际的Python SpooledTemporaryFile,您可以使用.file属性获取。示例如下。注意:pd.read_csv() isn't an async method,因此,如果您要使用async def端点,最好使用async方法读取文件的内容,如here所述,然后使用下面的一个reamining选项将内容传递给pd.read_csv()。(如here所述),它将在单独的线程中运行pd.read_csv(file.file),以确保主线程(运行协程的线程)不会被阻塞。

from fastapi import FastAPI, File, UploadFile
import pandas as pd

app = FastAPI()

@app.post("/upload")
def upload_file(file: UploadFile = File(...)):
    df = pd.read_csv(file.file)
    file.file.close()
    return {"filename": file.filename}

选项二

将字节转换为字符串,然后将其加载到内存中的文本缓冲区(即StringIO),该缓冲区可以转换为 Dataframe :

from fastapi import FastAPI, File, UploadFile
import pandas as pd
from io import StringIO

app = FastAPI()

@app.post("/upload")
def upload_file(file: UploadFile = File(...)):
    contents = file.file.read()
    s = str(contents,'utf-8')
    data = StringIO(s) 
    df = pd.read_csv(data)
    data.close()
    file.file.close()
    return {"filename": file.filename}

选项三

使用内存中的字节缓冲区(即BytesIO),从而节省了将字节转换为字符串的步骤,如选项2所示:

from fastapi import FastAPI, File, UploadFile
import pandas as pd
from io import BytesIO
import uvicorn

app = FastAPI()

@app.post("/upload")
def upload_file(file: UploadFile = File(...)):
    contents = file.file.read()
    data = BytesIO(contents)
    df = pd.read_csv(data)
    data.close()
    file.file.close()
    return {"filename": file.filename}

相关问题