Python多线程调用yfinance下载股票数据报错can't start new thread
错误原因
yfinance的download方法默认会为传入的每个股票标的分配独立线程执行下载任务,你一次性传入5467个标的,远超过操作系统允许的单进程最大线程数,因此触发Runtime Error: can't start new thread报错。
最优修复方案
无需自行改写下载逻辑,直接使用yfinance内置的并发数限制参数即可,仅需在调用download方法时添加threads参数指定最大并发线程数,数值可根据设备性能、网络带宽调整,通常设置为4~32区间即可:
# 限制最大并发线程为8,既不会触发线程超限,也能充分利用带宽提升下载速度 stock_prices_daily = yf.download(ticker_daily, group_by='Ticker', start = '1990-01-01', threads=8)
自定义逻辑优化建议
如果你需要在下载过程中做额外的字段处理、失败重试等自定义操作,可以采用批量拆分标的+多线程分批下载+一次性合并结果的方案,效率远高于你当前使用的单标的串行循环方案:
- 将5467个标的拆分为多个小批次,每批次包含50~200个标的
- 单批次内启用多线程下载,完成一批再处理下一批,避免线程数超限
- 不要使用
pandas.DataFrame.append方法逐次拼接结果,该方法已被废弃且内存效率极低,可将所有下载完成的临时DataFrame存入列表,最后用pd.concat一次性合并
优化后的示例代码如下:
import pandas as pd # 每批下载的标的数量,可根据实际情况调整 batch_size = 100 temp_df_list = [] # 拆分标的列表为小批次 ticker_batches = [ticker_daily[i:i+batch_size] for i in range(0, len(ticker_daily), batch_size)] for batch in ticker_batches: # 单批次内启用10线程下载 batch_raw = yf.download(batch, start='1990-01-01', group_by='Ticker', threads=10) # 转换为带Ticker字段的长表格式,和你原循环输出格式一致 batch_formatted = batch_raw.stack(level=0).rename_axis(['Date', 'Ticker']).reset_index(level=1) temp_df_list.append(batch_formatted) # 一次性合并所有批次的下载结果 stock_prices = pd.concat(temp_df_list, ignore_index=False)
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

