使用Pandas DataReader调用Morningstar API遇特定股票代码崩溃求助
I’ve run into similar headaches with the Morningstar API and pandas_datareader where certain invalid or unsupported tickers trigger stuck retry loops that eventually crash Python entirely. Here’s how you can resolve this:
Root Cause
The "adding [ticker] to retry list" message means pandas_datareader is repeatedly attempting to re-fetch data for these tickers. For some unsupported entries, the API might return malformed responses, or the retry logic gets stuck in an infinite loop—leading to a hard crash instead of a catchable exception.
Solution 1: Enforce a Timeout to Prevent Hanging
Since standard try-except blocks often fail to catch the crash (it’s likely a low-level segfault or unhandled error), use Python’s signal module to set a hard timeout on the DataReader call. This will terminate the request if it takes too long, letting you skip the problematic ticker gracefully.
import pandas as pd import pandas_datareader.data as web import signal class TimeoutError(Exception): pass def timeout_handler(signum, frame): raise TimeoutError("Request exceeded time limit") def fetch_morningstar_data(ticker, start_date, timeout=10): # Set up timeout signal signal.signal(signal.SIGALRM, timeout_handler) signal.alarm(timeout) try: df = web.DataReader(ticker, "morningstar", start_date) signal.alarm(0) # Cancel timeout if request succeeds return df except TimeoutError: print(f"Skipping {ticker}: Request timed out") return None except Exception as e: print(f"Skipping {ticker}: {str(e)}") return None # Example usage tickers = ['AAPL', 'BBXTB', 'CRXPF', 'IMMVD', 'FFRMF'] start_date = '2023-01-01' for ticker in tickers: data = fetch_morningstar_data(ticker, start_date) if data is not None: # Process your data here print(f"Successfully retrieved data for {ticker}")
Solution 2: Pre-Validate Tickers Before Fetching
Avoid even calling DataReader for invalid tickers by first checking if the ticker exists on Morningstar with a lightweight request. This saves you from triggering the problematic retry logic altogether:
import requests def is_valid_morningstar_ticker(ticker): # Check if the ticker's quote page exists url = f"https://www.morningstar.com/stocks/xnas/{ticker}/quote" try: response = requests.get(url, timeout=5) return response.status_code == 200 and "Not Found" not in response.text except Exception: return False # Example usage for ticker in tickers: if is_valid_morningstar_ticker(ticker): data = web.DataReader(ticker, "morningstar", start_date) # Process your data here else: print(f"Skipping {ticker}: Invalid or unsupported ticker")
Key Notes
- For maximum robustness, combine both solutions: pre-validate tickers first, then use the timeout wrapper for the DataReader call.
- If you’re on Windows, the
signalmodule’s SIGALRM won’t work—use thethreadingmodule to implement a timeout instead (search for "Python threading timeout function" for examples).
内容的提问来源于stack exchange,提问作者user8025285




