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

.ipynb代码正常运行但同名.py文件触发IndexError问题求助

问题:Notebook代码可正常运行,转为.py文件后触发IndexError

问题描述

在VS Code中开发Python项目,通过Eikon API获取数据并存入sqlite3数据库。Jupyter Notebook格式的代码能成功将数据上传至数据库,但将相同代码转为.py文件运行时,触发IndexError:访问df.index[0]时索引越界。已尝试调整列名、数据类型等操作,问题仍未解决。

Jupyter Notebook代码

# %%
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import eikon as ek 
import json
import datetime as dt
import sqlite3 as sql


# %%
ek.set_app_key('45a807bae5a6416c8aaf5be32d64c3be68e5e623')

# %%
with open('ProductDataJson2.json', 'r') as json_file:
    data = json.load(json_file)

# %%
fields_array=['OPEN','HIGH','LOW','CLOSE','VOLUME']

# %%
df=pd.DataFrame(columns=['RIC(i)','Category']+fields_array)

# %%
def geteikondata_daily(ric,fields,start_date,end_date):
    
    df=pd.DataFrame()
    start_date1=start_date
    end_date1=end_date
    while True:
        try:
            tmp_df=ek.get_timeseries(ric, interval = 'daily', start_date = start_date1, \
                                   end_date = end_date1, fields=fields)
            df=pd.concat([tmp_df,df])
            end_date1=df.index[0]-dt.timedelta(microseconds=1)
            end_date1=dt.datetime.fromtimestamp(dt.datetime.timestamp(end_date1))
        except ek.EikonError as err:
           print(err)
           break
    return df

# %%
for category, product_list in data.items():
    for product in product_list:
        ric=product['RIC']
        fields=['OPEN','HIGH','LOW','CLOSE']
        end_date = dt.datetime.utcnow()
        start_date = end_date - dt.timedelta(days=5)
        ric_symbols=[f"{ric}c{i}" for i in range(1,2)]
        for ric_symbol in ric_symbols:
            retrived_data=geteikondata_daily(ric_symbol,fields,start_date,end_date)
            if not retrived_data.empty:
                retrived_data=retrived_data.reindex(columns=fields_array,fill_value=pd.NA)
                retrived_data=retrived_data.reset_index()
                retrived_data['RIC(i)']=ric_symbol
                retrived_data['Category']= category
                df=pd.concat([df,retrived_data],ignore_index=True)
                print(df)
            else:
                print(f"Data for {ric_symbol} is empty, skipping .....")

# %%
conn = sql.connect('my_database.db')
df.to_sql('my_table', conn, if_exists='replace', index=False)

Python脚本代码

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import eikon as ek 
import json
import datetime as dt
import sqlite3  as sql

with open('ProductDataJson2.json', 'r') as json_file:
    data = json.load(json_file)

fields_array=['OPEN','HIGH','LOW','CLOSE','VOLUME']

df=pd.DataFrame(columns=['RIC(i)','Category']+fields_array)

def geteikondata_daily(ric,fields,start_date,end_date):
    
    df=pd.DataFrame()
    start_date1=start_date
    end_date1=end_date
    while True:
        try:
            tmp_df=ek.get_timeseries(ric, interval = 'daily', start_date = start_date1,end_date = end_date1, fields=fields)
            df=pd.concat([tmp_df,df])
            end_date1=df.index[0]-dt.timedelta(microseconds=1)
            end_date1=dt.datetime.fromtimestamp(dt.datetime.timestamp(end_date1))
        except ek.EikonError as err:
           print(err)
           break
    return df

for category, product_list in data.items():
    for product in product_list:
        ric=product['RIC']
        fields=['OPEN','HIGH','LOW','CLOSE']
        end_date = dt.datetime.utcnow()
        start_date = end_date - dt.timedelta(days=3)
        ric_symbols=[f"{ric}c{i}" for i in range(1,3)]
        for ric_symbol in ric_symbols:
            retrived_data=geteikondata_daily(ric_symbol,fields,start_date,end_date)
            if not retrived_data.empty:
                retrived_data=retrived_data.reindex(columns=fields_array,fill_value=pd.NA)
                retrived_data=retrived_data.reset_index()
                retrived_data['RIC(i)']=ric_symbol
                retrived_data['Category']= category
                df=pd.concat([df,retrived_data],ignore_index=True)
                print(df)
            else:
                print(f"Data for {ric_symbol} is empty, skipping .....")

conn = sql.connect('my_database.db')
df.to_sql('my_table', conn, if_exists='replace', index=False)

报错信息

Traceback (most recent call last):
  File "c:\Users\Project 3 - Market Movement\Back\test.py", line 41, in <module>
    retrived_data=geteikondata_daily(ric_symbol,fields,start_date,end_date)
  File "c:\Users\Project 3 - Market Movement\Back\test.py", line 26, in geteikondata_daily
    end_date1=df.index[0]-dt.timedelta(microseconds=1)
  File "c:\programdata\anaconda3\lib\site-packages\pandas\core\indexes\base.py", line 5320, in __getitem__
    return getitem(key)
IndexError: index 0 is out of bounds for axis 0 with size 0

问题原因与解决办法

原因

在geteikondata_daily函数中,当ek.get_timeseries返回空DataFrame时(比如目标RIC无可用数据、API返回为空),pd.concat([tmp_df, df])后的df仍然是空的,此时直接访问df.index[0]就会触发索引越界错误。

Notebook中未触发该错误,是因为测试的RIC范围更小(range(1,2)),没遇到无数据的情况;而.py脚本遍历了更多RIC(range(1,3)),刚好命中了无数据的场景。

解决办法

在访问df.index[0]前,先检查df是否为空,为空则直接跳出循环:
修改后的geteikondata_daily函数:

def geteikondata_daily(ric,fields,start_date,end_date):
    
    df=pd.DataFrame()
    start_date1=start_date
    end_date1=end_date
    while True:
        try:
            tmp_df=ek.get_timeseries(ric, interval = 'daily', start_date = start_date1,end_date = end_date1, fields=fields)
            # 当前请求返回空,直接终止循环
            if tmp_df.empty:
                break
            df=pd.concat([tmp_df,df])
            # 确认df非空再访问索引
            if df.empty:
                break
            end_date1=df.index[0]-dt.timedelta(microseconds=1)
            end_date1=dt.datetime.fromtimestamp(dt.datetime.timestamp(end_date1))
        except ek.EikonError as err:
           print(err)
           break
    return df

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 18:15:11