簡體   English   中英

是否可以允許用戶在 FastAPI 或 Flask 中下載 pyspark 數據幀的結果

[英]Is it possible to allow users to download the result of a pyspark dataframe in FastAPI or Flask

我正在使用 FastAPI 開發一個 API,用戶可以向它發出請求,以便發生以下情況:

  1. 首先,get 請求將從 Google Cloud Storage 中獲取一個文件並將其加載到 pyspark DataFrame 中
  2. 然后應用程序將對 DataFrame 執行一些轉換
  3. 最后,我想將 DataFrame 作為鑲木地板文件寫入用戶的磁盤。

由於以下幾個原因,我無法弄清楚如何以鑲木地板格式將文件交付給用戶:

  • df.write.parquet('out/path.parquet')將數據寫入df.write.parquet('out/path.parquet')的目錄中out/path.parquet當我嘗試將其傳遞給starlette.responses.FileResponse時,這會帶來挑戰
  • 將我知道存在的單個 .parquet 文件傳遞​​給starlette.responses.FileResponse似乎只是將二進制文件打印到我的控制台(如下面的代碼所示)
  • 像在Pandas 中那樣將 DataFrame 寫入 BytesIO 流似乎很有希望,但我無法弄清楚如何使用任何 DataFrame 的方法或 DataFrame.rdd 的方法來做到這一點。

這在 FastAPI 中甚至可能嗎? 是否可以在 Flask 中使用send_file()

這是我到目前為止的代碼。 請注意,我已經嘗試了一些諸如注釋代碼之類的方法,但無濟於事。

import tempfile

from fastapi import APIRouter
from pyspark.context import SparkContext
from pyspark.sql.session import SparkSession
from starlette.responses import FileResponse


router = APIRouter()
sc = SparkContext('local')
spark = SparkSession(sc)

df: spark.createDataFrame = spark.read.parquet('gs://my-bucket/sample-data/my.parquet')

@router.get("/applications")
def applications():
    df.write.parquet("temp.parquet", compression="snappy")
    return FileResponse("part-some-compressed-file.snappy.parquet")
    # with tempfile.TemporaryFile() as f:
    #     f.write(df.rdd.saveAsPickleFile("temp.parquet"))
    #     return FileResponse("test.parquet")

謝謝!

編輯:我嘗試使用此處提供的答案和信息,但我無法讓它正常工作。

我能夠解決這個問題,但它遠非優雅。 如果有人可以提供不寫入磁盤的解決方案,我將不勝感激,並將選擇您的答案作為正確答案。

我能夠使用df.rdd.saveAsPickleFile()序列化 DataFrame,壓縮生成的目錄,將其傳遞給 python 客戶端,將生成的 zipfile 寫入磁盤,解壓縮它,然后在最終加載SparkContext().pickleFile之前使用SparkContext().pickleFile pickleFile . 遠非理想,我認為。

應用程序接口:

import shutil
import tempfile

from fastapi import APIRouter
from pyspark.context import SparkContext
from pyspark.sql.session import SparkSession
from starlette.responses import FileResponse


router = APIRouter()
sc = SparkContext('local')
spark = SparkSession(sc)

df: spark.createDataFrame = spark.read.parquet('gs://my-bucket/my-file.parquet')

@router.get("/applications")
def applications():
    temp_parquet = tempfile.NamedTemporaryFile()
    temp_parquet.close()
    df.rdd.saveAsPickleFile(temp_parquet.name)

    shutil.make_archive('test', 'zip', temp_parquet.name)

    return FileResponse('test.zip')

客戶:

import io
import zipfile

import requests

from pyspark.context import SparkContext
from pyspark.sql.session import SparkSession

sc = SparkContext('local')
spark = SparkSession(sc)

response = requests.get("http://0.0.0.0:5000/applications")
file_like_object = io.BytesIO(response.content)
with zipfile.ZipFile(file_like_object) as z:
    z.extractall('temp.data')

rdd = sc.pickleFile("temp.data")
df = spark.createDataFrame(rdd)

print(df.head())

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM