You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django+Pandas应用部署Railway后特定页面加载失败排查

问题:Django DRF + Pandas 应用部署后页面加载失败,本地慢但可用

使用Django Rest Framework开发、集成Pandas数据处理的应用,本地服务器特定页面加载耗时10-11秒,但部署到Railway平台后,该页面无法加载且持续返回应用服务器错误。应用采用DRF构建API,相关视图及辅助函数代码如下:

视图代码

def nsebse(request):
    if request.user.is_authenticated:
        endpoint1 = rq.get('https://stockindex.up.railway.app/api/bse/').json()
        endpoint2 = rq.get('https://stockindex.up.railway.app/api/nse/').json()
        bseData = helperForBSENSE(endpoint1)
        nseData = helperForBSENSE(endpoint2)
        return render(request,'nsebse.html',{'bseData':bseData,'nseData':nseData})
    else:
        return render(request,'notauth.html')

辅助函数代码

def helperForBSENSE(data):
    df = pd.DataFrame(columns = ['id','date','open','high','low','close','adj_close','volume'])
    for i in range(len(data)):
        item = data[i]
        df.loc[i] = [item['id'],item['date'],item['open'],item['high'],item['low'],item['close'],item['adj_close'],item['volume']]
        df['date']= pd.to_datetime(df['date'])
    today, req_day = datetime(2023,1,12), datetime(2022,1,12)

    one_year_df = df[(df['date'] <= today) & (df['date'] > req_day)]
    fifty_two_week_high = max(one_year_df['high'])
    fifty_two_week_low = min(one_year_df['low'])

    day_high = df[df['date']==today]['high']
    day_low = df[df['date']==today]['low']

    previous_day = today - pd.Timedelta(days=1)
    today_close = float(df[df['date']==today]['close'])
    prev_close = float(df[df['date']==previous_day]['close'])

    today_open = float(df[df['date']==today]['open'])
    today_gain_or_loss = float(today_close - prev_close)

    data = {
            'today_open':today_open,
            'today_close':today_close,
            'prev_close': prev_close,
            'today_gain_or_loss' : today_gain_or_loss,
            'day_high':float(day_high),
            'day_low':float(day_low),
            'fifty_two_week_high':fifty_two_week_high,
            'fifty_two_week_low':fifty_two_week_low,
            'xAxis':list(df['date']),
            'yAxis':list(df['close']),
            }
    return data

可能成因

  • 内部请求循环与超时:视图中直接调用自身公网API地址,在Railway环境中,内部请求可能因网络策略、端口映射问题无法正常访问,导致请求超时触发5xx错误;本地因localhost网络延迟低,仅表现为加载缓慢。
  • Pandas数据处理效率极低:辅助函数用df.loc[i]逐行循环构建DataFrame,这是Pandas中性能最差的操作之一,数据量大时会导致CPU占用过高、处理时间过长。本地硬件资源充足勉强运行,但Railway基础实例资源有限,直接触发超时或资源耗尽。
  • 硬编码日期与数据缺失:代码中硬编码today = datetime(2023,1,12),若部署后数据库无该日期记录,df[df['date']==today]返回空DataFrame,后续float(day_high)等操作会抛出ValueError,引发服务器内部错误。
  • Railway资源限制:Railway基础实例的CPU、内存配额较低,Pandas大量数据处理易触发资源限制,进程被平台终止后返回5xx错误。
  • 无异常捕获机制:视图及辅助函数未添加异常捕获,一旦API请求失败、数据格式错误或Pandas处理出错,直接抛出未捕获异常,导致服务器返回500错误。

排查方法

  1. 查看Railway实时日志:在Railway控制台查看应用日志,定位具体错误信息(如超时堆栈、异常类型),这是最直接的问题定位方式。
  2. 验证内部API可达性:在Railway环境中用内部域名(而非公网域名)测试API调用,确认内部请求是否正常;避免在视图中调用自身公网API,直接从数据库或DRF序列化器获取数据。
  3. 模拟资源限制测试:本地用工具限制应用CPU、内存(如cpulimit),模拟Railway资源环境,复现是否出现超时或崩溃。
  4. 检查数据完整性:确认部署后数据库中存在硬编码日期的记录,且数据格式与本地一致。
  5. 添加异常捕获与日志:在视图和辅助函数中加入try-except块,捕获HTTP请求、Pandas处理异常,并记录详细日志。

代码优化建议

1. 重构Pandas DataFrame构建逻辑

避免逐行loc赋值,直接从列表生成DataFrame,效率提升数倍:

def helperForBSENSE(data):
    # 直接从数据列表生成DataFrame,跳过逐行赋值
    df = pd.DataFrame(data, columns=['id','date','open','high','low','close','adj_close','volume'])
    df['date'] = pd.to_datetime(df['date'])
    # 后续逻辑不变...

2. 取消内部HTTP请求,直接操作数据库

跳过API请求环节,直接从DRF QuerySet获取数据:

from .models import BSEData, NSEData
from .serializers import BSEDataSerializer, NSEDataSerializer

def nsebse(request):
    if request.user.is_authenticated:
        # 直接从数据库查询并序列化
        bse_data = BSEDataSerializer(BSEData.objects.all(), many=True).data
        nse_data = NSEDataSerializer(NSEData.objects.all(), many=True).data
        bseData = helperForBSENSE(bse_data)
        nseData = helperForBSENSE(nse_data)
        return render(request,'nsebse.html',{'bseData':bseData,'nseData':nseData})
    else:
        return render(request,'notauth.html')

3. 处理数据缺失场景

添加空值判断,避免因数据缺失抛出异常:

# 替换原日期查询逻辑
today_row = df[df['date'] == today]
if not today_row.empty:
    day_high = float(today_row['high'].iloc[0])
    day_low = float(today_row['low'].iloc[0])
    today_close = float(today_row['close'].iloc[0])
    today_open = float(today_row['open'].iloc[0])
else:
    # 设置默认值或返回友好提示
    day_high = day_low = today_close = today_open = 0.0

prev_day_row = df[df['date'] == previous_day]
prev_close = float(prev_day_row['close'].iloc[0]) if not prev_day_row.empty else 0.0

4. 动态计算日期,替换硬编码

用当前日期动态计算时间范围:

from datetime import timedelta

today = pd.Timestamp.today().normalize()
req_day = today - timedelta(days=365)
previous_day = today - timedelta(days=1)

内容的提问来源于stack exchange,提问作者Ashish Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 09:10:37