Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >FastAPI返回大量JSON数据的速度非常慢

FastAPI返回大量JSON数据的速度非常慢
EN

Stack Overflow用户
提问于 2022-08-31 21:51:59
回答 2查看 1.2K关注 0票数 2

我有一个FastAPI GET端点,它返回大量JSON数据(~160,000行和45列)。毫不奇怪,使用json.dumps()返回数据的速度非常慢。我首先使用json.loads()从文件中读取数据,然后根据输入的参数对其进行过滤。是否有比使用return data更快地将数据返回给用户的方法?在目前的状态下,这需要近一分钟的时间。

我的代码当前如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# helper function to parse parquet file (where data is stored)
def parse_parquet(file_path):
    df = pd.read_parquet(file_path)
    result = df.to_json(orient = 'records')
    parsed = json.loads(result)
    return parsed
    

@app.get('/endpoint')
# has several more parameters
async def some_function(year = int | None = None, id = str | None = None):
    if year is None:
        data = parse_parquet(f'path/{year}_data.parquet')
    # no year
    if year is not None:
        data = parse_parquet(f'path/all_data.parquet')
    if id is not None:
        data = [d for d in data if d['id'] == id]
    return data
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-09-02 00:55:37

响应如此缓慢的原因之一是,在您的parse_parquet()方法中,首先将文件转换为JSON (使用df.to_json()),然后转换为字典(使用json.loads()),最后再转换为JSON,作为FastAPI,在幕后使用jsonable_encoder将返回的值转化为与JSON兼容的数据,然后使用Python json.dumps()来序列化对象--这个过程非常慢(更多细节见这个答案 )。

正如@MatsLindh在注释部分中所建议的那样,您可以使用替代的JSON编码器,例如奥尔森尤约森,这确实会加快进程,而不是让FastAPI使用jsonable_encoder,然后让标准json.dumps()将数据转换为JSON。然而,,使用熊猫to_json()并直接重新定制Response --正如这个答案-seems的选项1 (Update 2)所描述的那样,它是性能最好的解决方案。您可以使用下面给出的代码--它使用班级-to来比较所有可用解决方案的响应时间。

使用您自己的拼花文件或下面的代码创建一个由160 K行和45列组成的样例拼花文件。

create_parquet.py

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import pandas as pd
import numpy as np

columns = ['C' + str(i) for i in range(1, 46)]
df = pd.DataFrame(data=np.random.randint(99999, 99999999, size=(160000,45)),columns=columns)
df.to_parquet('data.parquet')

运行下面的FastAPI应用程序,并分别访问每个端点,以检查完成将数据加载和转换为JSON过程所需的时间。

app.py

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from fastapi import FastAPI, APIRouter, Response, Request
from fastapi.routing import APIRoute
from typing import Callable
import pandas as pd
import json
import time
import ujson
import orjson


class TimedRoute(APIRoute):
    def get_route_handler(self) -> Callable:
        original_route_handler = super().get_route_handler()

        async def custom_route_handler(request: Request) -> Response:
            before = time.time()
            response: Response = await original_route_handler(request)
            duration = time.time() - before
            response.headers["Response-Time"] = str(duration)
            print(f"route duration: {duration}")
            return response

        return custom_route_handler

app = FastAPI()
router = APIRouter(route_class=TimedRoute)

@router.get("/defaultFastAPIencoder")
def get_data_default():
    df = pd.read_parquet('data.parquet')   
    return df.to_dict(orient="records")
    
@router.get("/orjson")
def get_data_orjson():
    df = pd.read_parquet('data.parquet')
    return Response(orjson.dumps(df.to_dict(orient='records')), media_type="application/json")

@router.get("/ujson")
def get_data_ujson():
    df = pd.read_parquet('data.parquet')   
    return Response(ujson.dumps(df.to_dict(orient='records')), media_type="application/json")

# Preferable way to do it  
@router.get("/pandasJSON")
def get_data_pandasJSON():
    df = pd.read_parquet('data.parquet')   
    return Response(df.to_json(orient="records"), media_type="application/json")  

app.include_router(router)

尽管使用上面的/pandasJSON响应时间相当快(这是最好的方法),但在浏览器上显示数据时可能会遇到一些延迟。然而,这与服务器端无关,而与客户端有关,因为浏览器试图显示大量数据。如果您不想显示数据,而是让用户将数据下载到他们的设备(这会快得多),您可以使用Content-Disposition参数将Response头设置为Response,并传递一个filename,指示浏览器应该下载该文件。有关更多细节,请查看这个答案这个答案

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@router.get("/download")
def get_data():
    df = pd.read_parquet('data.parquet')
    headers = {'Content-Disposition': 'attachment; filename="data.json"'}
    return Response(df.to_json(orient="records"), headers=headers, media_type='application/json')

我还应该提到,有一个名为Dask的库,它可以处理大型数据集,如这里所描述的那样,以防您必须处理大量记录,并且要花费太长时间才能完成该过程。与Pandas类似,您可以使用.read_parquet()方法读取文件。由于Dask似乎没有提供等效的.to_json()方法,所以可以使用df.compute()将Dask DataFrame转换为Pandas DataFrame,然后使用Pandas df.to_json()将DataFrame转换为JSON字符串,并按上面所示返回。

票数 4
EN

Stack Overflow用户

发布于 2022-08-31 22:53:05

我猜在您的情况下,json.loads(result)将返回一个dict数据类型,并且您正在过滤dict数据类型。您可以将dict数据类型发送为JSON,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from fastapi.responses import JSONResponse

@app.get('/endpoint')
# has several more parameters
async def some_function(year = int | None = None, id = str | None = None):
    if year is None:
        data = parse_parquet(f'path/{year}_data.parquet')
    # no year
    if year is not None:
        data = parse_parquet(f'path/all_data.parquet')
    if id is not None:
        data = [d for d in data if d['id'] == id]
    return JSONResponse(content=json_compatible_item_data)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73564771

复制
相关文章
Xshell/Xftp连接Linux速度非常慢(已解决)
1、打开sshd服务的配置文件/etc/ssh/sshd_config,把UseDNS yes改为UseDNS no
Arebirth
2020/06/19
5.4K0
Php如何返回json数据(返回json对象或json格式数据)
header(‘Content-Type:application/json; charset=utf-8’);
超级小可爱
2023/02/20
17K0
struts返回json数据
  实际上就是在struts中获取response对象的输出流。然后写入你要返回的json数据,本质和用servlet返回json数据是一样的,需要自己导入json的jar包。不做详细介绍。
用户2038589
2018/09/06
2K0
struts返回json数据
FtpClient上传文件速度非常慢,而且大小为0,上传失败
添加代码:调用FTPClient的enterLocalPassiveMode();方法,设置为被动模式,既可以解决。
Arebirth
2020/06/19
2.7K0
Python Flask,Json,返回Json数据,jsonify
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/142981.html原文链接:https://javaforall.cn
全栈程序员站长
2022/08/31
1.9K0
django 返回 json 格式数据
1.返回的格式需要是json数据格式的时候,将content 格式为json对象即可: from django.http import HttpResponse import json def test(request): resp = { 'code': '200', 'message': 'success', 'data': { 'num': '1234', }, } response
onety码生
2018/11/21
2.8K0
FastAPI 学习之路(五十八)封装统一的json返回处理工具
我们之前分享FastAPI 学习之路(五十七)对之前的代码进行优化,我们这次分享对于响应的json数据做统一的格式化处理。
雷子
2021/10/12
3.4K0
Java后端返回Json数据规范
列表数据 在返回的json的中,有一个键值为data的Hashmap 使用mybatis plus无条件(wrapper为null,查询全部)查询所有用户的信息 所有信息返回一个list 将list放入hashmap中,键值为items
小颜同学
2023/08/24
1K0
[Go] golang http下返回json数据
从post中获取到字段后 , 返回对应的结果 , 设置header必须在返回响应码之前调用
唯一Chat
2020/05/26
8.6K0
Flask 使用json或者jsonify返回json响应数据的方法
在前后端分离的时代,后端一般返回前端的数据就是json格式的响应数据。 而json格式的响应数据其实实际上就是一个字符串。
Devops海洋的渔夫
2019/12/02
17.5K0
【说站】php返回json数据
PHP中的json_encode()用于JSON编码变量,如果功能成功返回JSON数据,则返回FALSE。
很酷的站长
2022/11/23
2.2K0
【说站】php返回json数据
物流信息接口 返回JSON数据
获取物流信息接口 【获取物流信息】 请求模式:GET/POST 请求地址:https://api.shunnet.top/logistics/api?companycode=ems&number=1
Shunnet
2021/06/11
1.1K0
FastAPI(45)- 返回响应数据的五种常见方式
默认情况下,路径操作函数可以返回 Python 数据类型、Pydantic Model,FastAPI 会自动将它们转换为和 JSON 兼容的数据
小菠萝测试笔记
2021/10/09
3K0
FastAPI(45)- 返回响应数据的五种常见方式
Json乱码问题和返回json数据统一解决
我们可以在springmvc的配置文件上添加一段消息StringHttpMessageConverter转换配置!
PHY_68
2020/10/28
1.2K0
[日常] 解决github速度特别慢
nslookup github.global.ssl.fastly.Net nslookup github.com
唯一Chat
2019/11/22
1.6K0
WebAPI返回JSON
web api写api接口时默认返回的是把你的对象序列化后以XML形式返回,那么怎样才能让其返回为json呢,下面就介绍两种方法:  方法一:(改配置法)  找到Global.asax文件,在Application_Start()方法中添加一句:
莫问今朝
2018/08/31
3.5K0
Django 2.1.7 查询数据返回json格式
在日常工作中,对于前端发送过来的请求,后端django大部分都是采用json格式返回,也有采用模板返回视图的方式。 在模板返回视图的方式的确很方便,但是如果涉及到动静分离、ajax请求这类,django就只能返回json格式的数据了。 那么这里就带来了一个问题,如何将django从数据库模型类中查询的数据以json格式放回前端。 然后前端如果获取读取返回过来的数据呢?
Devops海洋的渔夫
2019/09/18
3K0
Django 2.1.7 查询数据返回json格式
springmvc之返回json类型的数据给前端
1、加入三个Jar包 2、为方法加上@ResponseBody注解,方法直接返回相关信息。 使用ResponseBody注解需要在springmvc.xml文件中配置: <mvc:annotation
西西嘛呦
2020/08/26
1.1K0
springmvc之返回json类型的数据给前端
springcloud 返回的数据为XML 而不是JSON
本人的原因是因为引入了jackson-dataformat-xml依赖导致的,下面查看自己项目是否包含此依赖,如果包含的话,可以去掉。 有的人添加了下面注解后可以解决,不过我这里没有解决。还是依靠上图
qubianzhong
2019/04/01
2.3K0
springcloud 返回的数据为XML 而不是JSON
点击加载更多

相似问题

WP7存储大量数据的速度非常慢

20

Highcharts散点图,大量数据点运行速度非常慢

40

删除大量行的速度非常慢- SQL Server

31

Solr查询速度非常慢,具有大量的qf

13

使用DataContractSerializer过滤大量XmlNodes的速度非常慢

17
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文