【问题标题】:How to upload a file in FastAPI and convert it into a Pandas Dataframe?如何在 FastAPI 中上传文件并将其转换为 Pandas Dataframe? [关闭]
【发布时间】:2022-08-20 02:56:45
【问题描述】:

我想将文件上传到 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}

标签: python pandas dataframe fastapi


【解决方案1】:

下面提供了有关如何将 FastAPI 中上传的文件转换为 Pandas DataFrame 的各种选项。如果您想将 DataFrame 转换为 JSON 并将其返回给客户端,请查看 this answer。如果您想使用async def 端点而不是def,请查看this answer 了解如何以async 方式读取文件内容,以及this answer 以了解两者之间的区别使用defasync def。最好将 I/O 操作(在下面的选项中描述)包含在 try-except-finally 块中,以便您可以正确捕获/引发任何可能的异常和 close file 对象(如图所示 @987654324 @ 和 here)。

选项1

由于pandas.read_csv()可以接受file-like对象,所以可以直接传递UploadFilefile-like对象。 UploadFile 公开了一个实际的 Python SpooledTemporaryFile,您可以使用 .file 属性获得它。下面给出示例。注意:pd.read_csv() isn't an async method,因此,如果您要使用async def 端点,最好使用async 方法读取文件的内容,如here 所述,然后传递内容到pd.read_csv() 使用下面的扩孔选项之一。或者,您可以使用 Starlette 的run_in_threadpool()(如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}

选项 2

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

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}

选项 3

请改用内存中的字节缓冲区(即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}

【讨论】:

  • 克里斯,你能告诉我一件事,我如何在其他函数中使用这个 df 变量。
  • 如果您需要对该变量的只读访问权限,并且在读取它之前从不期望它被其他进程/请求更改,那么您也不打算同时拥有several workers(这将有自己的内存),您可以将其声明为global,如here 所述,或store it on the app instance。否则,请查看this
猜你喜欢
  • 1970-01-01
  • 2020-12-21
  • 2019-07-11
  • 2016-04-22
  • 2021-09-11
  • 2018-03-11
  • 1970-01-01
  • 2021-07-31
  • 2017-09-20
相关资源
最近更新 更多