Python — один из самых популярных языков для аналитики и науки о данных. Однако после того, как вы создали свою модель анализа или машинного обучения, вам понадобится способ, которым другие люди смогут получить к ней доступ. Часто лучший способ предоставить такой доступ — предоставить API. Хотя данные из API почти всегда возвращаются в формате JSON, у вас может возникнуть необходимость предоставить их в другом формате, таком как прямая загрузка в CSV или XLSX. Разрешение данным из вашего API поступать в этих форматах значительно облегчит неразработчикам быстрый доступ к данным из вашего API в соответствии с их рабочими процессами.

В этой статье я приведу пример того, как вернуть табличные данные, хранящиеся в популярном формате Pandas DataFrame, в JSON, CSV и XLSX, предоставив пример приложения FastAPI с маршрутами для каждого из них.

1. Отправка данных в формате JSON

По умолчанию все, что вы возвращаете в ответе FastAPI, будет сериализовано как JSON перед отправкой пользователю. Ниже приведен пример файла main.py, который возвращает содержимое Pandas DataFrame в формате JSON.

import pandas as pd
from fastapi import FastAPI
app = FastAPI()
@app.get("/json")
def get_json_data():
    df = pd.DataFrame(
        [["Canada", 10], ["USA", 20]], 
        columns=["team", "points"]
    )
    return df.to_dict(orient="records")

Скопировав код в свой файл main.py, вы можете запустить приложение FastAPI с помощью следующей команды:

uvicorn main:app --reload

Если вам нужна помощь в начале работы с FastAPI, посетите страницу https://fastapi.tiangolo.com/#installation.

После запуска приложения перейдите к документации по адресу: http://127.0.0.1:8000/docs. Перейдите на маршрут /json и отправьте запрос, нажав Попробовать, затем Выполнить. Вы должны увидеть следующий ответ:

Если вы работаете с разработчиками, это, вероятно, лучший способ отправки и получения данных. Однако, если вы работаете с аналитиками, которые предпочитают такие инструменты, как Excel, кодированию, лучше предлагать данные в одном из следующих двух форматов.

2. Отправка данных в виде CSV-файла

Самый простой формат файла для отправки табличных данных — это файл CSV. Для этого нам нужно будет использовать метод pandas DataFrame to_csv() и класс FastAPI StreamingResponse. На основе существующего кода мы добавим новый маршрут, который возвращает ответ StreamingResponse. Это позволит нам отправлять данные, хранящиеся в памяти, в виде прикрепленного файла в нашем ответе API.

from fastapi.responses import StreamingResponse # Add to Top
@app.get("/csv")
def get_csv_data():
    df = pd.DataFrame(
        [["Canada", 10], ["USA", 20]], 
        columns=["team", "points"]
    )
    return StreamingResponse(
        iter([df.to_csv(index=False)]),
        media_type="text/csv",
        headers={"Content-Disposition": f"attachment; filename=data.csv"}
)

Вернувшись к документам и выполнив маршрут /csv, вы получите следующий ответ со ссылкой для загрузки данных CSV.

Просто нажмите «Загрузить файл», и вы увидите начало загрузки:

После сохранения данных в файле CSV их можно легко просмотреть в текстовом редакторе или загрузить в Excel для дальнейшего анализа.

3. Отправка данных в электронной таблице Excel (.xlsx)

Хотя файлы CSV являются чрезвычайно переносимым форматом, некоторые люди предпочитают, чтобы данные были предварительно загружены в файл Excel. Процесс для этого очень похож на процесс для CSV, однако нам нужно еще несколько шагов, чтобы загрузить файл Excel в память и преобразовать его в объект, который мы можем передать нашему API. Чтобы мы могли читать и записывать файлы XLSX, нам потребуется пакет OpenPyxl. Вы можете скачать его с помощью следующей команды:

pip install openpyxl

После установки OpenPyxl мы можем добавить следующий код в наш файл main.py.

from io import BytesIO # Add to Top of File
@app.get("/xlsx")
def get_excel_data():
    df = pd.DataFrame(
        [["Canada", 10], ["USA", 20]], 
        columns=["team", "points"]
    )
    buffer = BytesIO()
    with pd.ExcelWriter(buffer) as writer:
        df.to_excel(writer, index=False)
    return StreamingResponse(
        BytesIO(buffer.getvalue()),
        media_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        headers={"Content-Disposition": f"attachment; filename=data.csv"}
)

Здесь происходит несколько вещей, поэтому я воспользуюсь моментом, чтобы объяснить. Сначала мы создаем буфер для хранения нашего файла Excel. Затем мы используем Pandas ExcelWriter для записи нашего файла Excel в буфер (см.: https://pandas.pydata.org/docs/reference/api/pandas.ExcelWriter. html#pandas.ExcelWriter). Наконец, мы загружаем содержимое буфера и приводим его к объекту BytesIO, который затем можем передать в StreamingResponse.

После добавления нового маршрута вы можете вернуться на страницу документации и попробовать его самостоятельно. Следуя той же схеме, что и для CSV, вы сможете загрузить файл xlsx и открыть его в Excel:

Вот и все! Теперь у вас есть все необходимое, чтобы предлагать форматы файлов JSON, CSV и XLSX для ваших табличных данных непосредственно из ваших приложений FastAPI.

Спасибо за прочтение!