fix(flask_server): 修复 pickle 反序列化后 JSON 序列化问题

问题修复:
- pickle 反序列化后 attrs 包含真实 DataFrame/Series 对象
- build_premium_result_from_attrs 需要兼容 Series 对象和字典格式
- API 层需要将 DataFrame/Series 转换为 JSON 可序列化格式

修复方案:
- build_premium_result_from_attrs 支持 pd.Series 和 dict 两种输入
- API 层将 DataFrame 转换为 records 格式(orient='records')
- API 层将 Series 索引转换为字符串日期
- 过滤内部缓存元数据(_cache_*)
This commit is contained in:
2026-05-23 23:57:39 +08:00
parent 3619e26bf1
commit 82d57af666

View File

@@ -460,12 +460,12 @@ def build_premium_result(premium_series: pd.Series) -> Dict:
}
def build_premium_result_from_attrs(premium_data: Dict) -> Dict:
def build_premium_result_from_attrs(premium_data) -> Dict:
"""
从 attrs 格式构建溢价率返回结果
从 attrs 格式构建溢价率返回结果(兼容 Series 对象和字典格式)
Args:
premium_data: attrs 中的溢价率数据,格式
premium_data: pd.Series 对象或字典格式:
{
'type': 'series',
'data': {date_str: premium_value, ...},
@@ -475,16 +475,25 @@ def build_premium_result_from_attrs(premium_data: Dict) -> Dict:
Returns:
包含 premium_series, latest_premium, premium_date, premium_stats 的字典
"""
if not premium_data or premium_data.get('type') != 'series':
# 处理 None
if premium_data is None:
return {}
# 从 dict 恢复为 Series
# 如果是 pd.Series 对象pickle 反序列化后)
if isinstance(premium_data, pd.Series):
premium_series = premium_data
# 如果是字典格式(旧 JSON 序列化格式)
elif isinstance(premium_data, dict):
if premium_data.get('type') != 'series':
return {}
premium_dict = premium_data.get('data', {})
if not premium_dict:
return {}
premium_series = pd.Series(premium_dict)
premium_series.index = pd.to_datetime(premium_series.index)
else:
return {}
premium_series.index.name = 'date'
# 转换为日期-溢价率列表
@@ -735,7 +744,18 @@ def get_ohlcv():
# 提取净值到顶层(方便调用方使用)
if 'nav' in attrs:
result['nav'] = attrs['nav']
nav_df = attrs['nav']
if isinstance(nav_df, pd.DataFrame):
# 将 DataFrame 转换为列表格式JSON 可序列化)
nav_df_copy = nav_df.reset_index().copy()
nav_df_copy['date'] = nav_df_copy['date'].dt.strftime('%Y-%m-%d')
nav_dict = {
'data': nav_df_copy.to_dict(orient='records'),
'count': len(nav_df_copy)
}
result['nav'] = nav_dict
else:
result['nav'] = nav_df
# 提取溢价率到顶层(调用业务函数处理格式)
if 'premium' in attrs:
@@ -743,6 +763,31 @@ def get_ohlcv():
if premium_result:
result.update(premium_result)
# 将 attrs 中的 DataFrame/Series 转换为字典格式(用于 JSON 序列化)
attrs_serializable = {}
for key, value in attrs.items():
if isinstance(value, pd.DataFrame):
df_copy = value.reset_index().copy()
if 'date' in df_copy.columns:
df_copy['date'] = df_copy['date'].dt.strftime('%Y-%m-%d')
attrs_serializable[key] = {
'data': df_copy.to_dict(orient='records'),
'count': len(df_copy)
}
elif isinstance(value, pd.Series):
# 将 Series 索引转换为字符串
series_copy = value.copy()
series_copy.index = series_copy.index.strftime('%Y-%m-%d')
attrs_serializable[key] = {
'type': 'series',
'data': series_copy.to_dict(),
'name': value.name
}
else:
attrs_serializable[key] = value
result['attrs'] = attrs_serializable
# 如果用户指定了类型但与自动检测不同,显示提示
if asset_type_param and detected_type != final_type:
result['type_override'] = {