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

2023-12-30

我想将文件上传到 FastAPI 后端并将其转换为 Pandas DataFrame。但是,我似乎不明白如何使用 FastAPI 来做到这一点UploadFile https://fastapi.tiangolo.com/tutorial/request-files/#uploadfile目的。更具体地说,我应该将什么传递给pd.read_csv()功能?

这是我的 FastAPI 端点:

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

下面给出了如何将上传的 FastAPI 文件转换为 Pandas DataFrame 的各种选项。如果您还想将 DataFrame 转换为 JSON 并将其返回给客户端,请查看这个答案 https://stackoverflow.com/a/71205127/17865804。如果您想使用async def端点而不是def,请看一下这个答案 https://stackoverflow.com/a/70667530/17865804关于如何读取文件内容async方式,以及这个答案 https://stackoverflow.com/a/71517830/17865804了解使用之间的区别def and async def。最好将 I/O 操作(在下面的示例中)包含在try-except-finally块(如图所示here https://stackoverflow.com/a/70657621/17865804 and here https://stackoverflow.com/a/70667530/17865804),以便您可以捕获/引发任何可能的异常并且close the file正确地从内存中释放对象并避免潜在的错误。

有关如何上传和读取CSV文件的相关答案可以找到here https://stackoverflow.com/a/74588435/17865804(给出使用 Jinja2 模板的示例),以及here https://stackoverflow.com/a/70655118/17865804(将上传的CSV文件转换为JSON并返回给客户端)和here https://stackoverflow.com/a/76044533/17865804(提供不使用外部库的解决方案)。

Option 1

Since pandas.read_csv() https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html可以接受一个file-like https://docs.python.org/3/glossary.html#term-file-like-object对象,你可以通过file-like的对象UploadFile https://fastapi.tiangolo.com/tutorial/request-files/#uploadfile直接地。UploadFile https://fastapi.tiangolo.com/tutorial/request-files/#uploadfile公开一个实际的PythonSpooledTemporaryFile https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile你可以使用.file属性。下面给出示例。注:pd.read_csv()不是一个async method https://stackoverflow.com/a/60368916,因此,如果您要使用async def端点,最好使用async方法,如上所述here https://stackoverflow.com/a/71517830/17865804,然后将内容传递给pd.read_csv()使用下面剩余的选项之一。或者,您可以使用 Starlette 的run_in_threadpool() https://github.com/encode/starlette/blob/b8ea367b4304a98653ec8ce9c794ad0ba6dcaf4b/starlette/concurrency.py#L35(如所描述的here https://stackoverflow.com/a/71517830/17865804),这将运行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}

Option 2

将字节转换为字符串,然后将其加载到内存中的文本缓冲区中(即,StringIO https://docs.python.org/3/library/io.html#io.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}

Option 3

使用内存中的字节缓冲区来代替(即,BytesIO https://docs.python.org/3/library/io.html#io.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}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐