Skip to content

Commit 4674a48

Browse files
committed
Deprecate 'debug' arg, improve 'logging' use
1 parent 1e941fc commit 4674a48

File tree

3 files changed

+67
-57
lines changed

3 files changed

+67
-57
lines changed

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,17 @@ yf.download(tickers = "SPY AAPL", # list of tickers
186186

187187
Review the [Wiki](https://github.com/ranaroussi/yfinance/wiki) for more options and detail.
188188

189+
### Logging
190+
191+
`yfinance` now uses the `logging` module. To control the detail of printed messages you simply change the level:
192+
```
193+
import logging
194+
logger = logging.getLogger('yfinance')
195+
logger.setLevel(logging.ERROR) # default: only print errors
196+
logger.setLevel(logging.CRITICAL) # disable printing
197+
logger.setLevel(logging.DEBUG) # verbose: print errors & debug info
198+
```
199+
189200
### Smarter scraping
190201

191202
To use a custom `requests` session (for example to cache calls to the

yfinance/base.py

Lines changed: 45 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ def history(self, period="1mo", interval="1d",
9494
start=None, end=None, prepost=False, actions=True,
9595
auto_adjust=True, back_adjust=False, repair=False, keepna=False,
9696
proxy=None, rounding=False, timeout=10,
97-
debug=True, raise_errors=False) -> pd.DataFrame:
97+
debug=None, # deprecated
98+
raise_errors=False) -> pd.DataFrame:
9899
"""
99100
:Parameters:
100101
period : str
@@ -135,31 +136,32 @@ def history(self, period="1mo", interval="1d",
135136
seconds. (Can also be a fraction of a second e.g. 0.01)
136137
Default is 10 seconds.
137138
debug: bool
138-
If passed as False, will suppress
139-
error message printing to console.
139+
If passed as False, will suppress message printing to console.
140+
DEPRECATED, will be removed in future version
140141
raise_errors: bool
141-
If True, then raise errors as
142-
exceptions instead of printing to console.
142+
If True, then raise errors as Exceptions instead of logging.
143143
"""
144144

145-
if raise_errors:
146-
debug = True
145+
if debug is not None:
146+
if debug:
147+
utils.print_once(f"Ticker.history(debug={debug}) argument is deprecated and will be removed in future version. Do this instead: logging.getLogger('yfinance').setLevel(logging.ERROR)")
148+
logging.getLogger('yfinance').setLevel(logging.ERROR)
149+
else:
150+
utils.print_once(f"Ticker.history(debug={debug}) argument is deprecated and will be removed in future version. Do this instead to suppress error messages: logging.getLogger('yfinance').setLevel(logging.CRITICAL)")
151+
logging.getLogger('yfinance').setLevel(logging.CRITICAL)
147152

148153
if start or period is None or period.lower() == "max":
149154
# Check can get TZ. Fail => probably delisted
150-
tz = self._get_ticker_tz(debug, proxy, timeout)
155+
tz = self._get_ticker_tz(proxy, timeout)
151156
if tz is None:
152157
# Every valid ticker has a timezone. Missing = problem
153158
err_msg = "No timezone found, symbol may be delisted"
154159
shared._DFS[self.ticker] = utils.empty_df()
155160
shared._ERRORS[self.ticker] = err_msg
156-
if debug:
157-
if raise_errors:
158-
raise Exception('%s: %s' % (self.ticker, err_msg))
159-
else:
160-
logger.error('- %s: %s' % (self.ticker, err_msg))
161+
if raise_errors:
162+
raise Exception('%s: %s' % (self.ticker, err_msg))
161163
else:
162-
logger.debug('- %s: %s' % (self.ticker, err_msg))
164+
logger.error('%s: %s' % (self.ticker, err_msg))
163165
return utils.empty_df()
164166

165167
if end is None:
@@ -200,15 +202,15 @@ def history(self, period="1mo", interval="1d",
200202

201203
data = None
202204

205+
get_fn = self._data.get
206+
if end is not None:
207+
end_dt = _pd.Timestamp(end, unit='s').tz_localize("UTC")
208+
dt_now = end_dt.tzinfo.localize(_datetime.datetime.utcnow())
209+
data_delay = _datetime.timedelta(minutes=30)
210+
if end_dt+data_delay <= dt_now:
211+
# Date range in past so safe to fetch through cache:
212+
get_fn = self._data.cache_get
203213
try:
204-
get_fn = self._data.get
205-
if end is not None:
206-
end_dt = _pd.Timestamp(end, unit='s').tz_localize("UTC")
207-
dt_now = end_dt.tzinfo.localize(_datetime.datetime.utcnow())
208-
data_delay = _datetime.timedelta(minutes=30)
209-
if end_dt+data_delay <= dt_now:
210-
# Date range in past so safe to fetch through cache:
211-
get_fn = self._data.cache_get
212214
data = get_fn(
213215
url=url,
214216
params=params,
@@ -251,13 +253,10 @@ def history(self, period="1mo", interval="1d",
251253
if fail:
252254
shared._DFS[self.ticker] = utils.empty_df()
253255
shared._ERRORS[self.ticker] = err_msg
254-
if debug:
255-
if raise_errors:
256-
raise Exception('%s: %s' % (self.ticker, err_msg))
257-
else:
258-
logger.error('%s: %s' % (self.ticker, err_msg))
256+
if raise_errors:
257+
raise Exception('%s: %s' % (self.ticker, err_msg))
259258
else:
260-
logger.debug('%s: %s' % (self.ticker, err_msg))
259+
logger.error('%s: %s' % (self.ticker, err_msg))
261260
return utils.empty_df()
262261

263262
# parse quotes
@@ -271,13 +270,10 @@ def history(self, period="1mo", interval="1d",
271270
except Exception:
272271
shared._DFS[self.ticker] = utils.empty_df()
273272
shared._ERRORS[self.ticker] = err_msg
274-
if debug:
275-
if raise_errors:
276-
raise Exception('%s: %s' % (self.ticker, err_msg))
277-
else:
278-
logger.error('%s: %s' % (self.ticker, err_msg))
273+
if raise_errors:
274+
raise Exception('%s: %s' % (self.ticker, err_msg))
279275
else:
280-
logger.debug('%s: %s' % (self.ticker, err_msg))
276+
logger.error('%s: %s' % (self.ticker, err_msg))
281277
return shared._DFS[self.ticker]
282278

283279
# 2) fix weired bug with Yahoo! - returning 60m for 30m bars
@@ -394,13 +390,10 @@ def history(self, period="1mo", interval="1d",
394390
err_msg = "back_adjust failed with %s" % e
395391
shared._DFS[self.ticker] = utils.empty_df()
396392
shared._ERRORS[self.ticker] = err_msg
397-
if debug:
398-
if raise_errors:
399-
raise Exception('%s: %s' % (self.ticker, err_msg))
400-
else:
401-
logger.error('%s: %s' % (self.ticker, err_msg))
393+
if raise_errors:
394+
raise Exception('%s: %s' % (self.ticker, err_msg))
402395
else:
403-
logger.debug('%s: %s' % (self.ticker, err_msg))
396+
logger.error('%s: %s' % (self.ticker, err_msg))
404397

405398
if rounding:
406399
df = _np.round(df, data[
@@ -932,7 +925,7 @@ def _fix_zeroes(self, df, interval, tz_exchange, prepost, silent=False):
932925

933926
return df3
934927

935-
def _get_ticker_tz(self, debug_mode, proxy, timeout):
928+
def _get_ticker_tz(self, proxy, timeout):
936929
if self._tz is not None:
937930
return self._tz
938931
cache = utils.get_tz_cache()
@@ -944,7 +937,7 @@ def _get_ticker_tz(self, debug_mode, proxy, timeout):
944937
tz = None
945938

946939
if tz is None:
947-
tz = self._fetch_ticker_tz(debug_mode, proxy, timeout)
940+
tz = self._fetch_ticker_tz(proxy, timeout)
948941

949942
if utils.is_valid_timezone(tz):
950943
# info fetch is relatively slow so cache timezone
@@ -955,7 +948,7 @@ def _get_ticker_tz(self, debug_mode, proxy, timeout):
955948
self._tz = tz
956949
return tz
957950

958-
def _fetch_ticker_tz(self, debug_mode, proxy, timeout):
951+
def _fetch_ticker_tz(self, proxy, timeout):
959952
# Query Yahoo for fast price data just to get returned timezone
960953

961954
params = {"range": "1d", "interval": "1d"}
@@ -967,25 +960,22 @@ def _fetch_ticker_tz(self, debug_mode, proxy, timeout):
967960
data = self._data.cache_get(url=url, params=params, proxy=proxy, timeout=timeout)
968961
data = data.json()
969962
except Exception as e:
970-
if debug_mode:
971-
print("Failed to get ticker '{}' reason: {}".format(self.ticker, e))
963+
logger.error("Failed to get ticker '{}' reason: {}".format(self.ticker, e))
972964
return None
973965
else:
974966
error = data.get('chart', {}).get('error', None)
975967
if error:
976968
# explicit error from yahoo API
977-
if debug_mode:
978-
print("Got error from yahoo api for ticker {}, Error: {}".format(self.ticker, error))
969+
logger.debug("Got error from yahoo api for ticker {}, Error: {}".format(self.ticker, error))
979970
else:
980971
try:
981972
return data["chart"]["result"][0]["meta"]["exchangeTimezoneName"]
982973
except Exception as err:
983-
if debug_mode:
984-
print("Could not get exchangeTimezoneName for ticker '{}' reason: {}".format(self.ticker, err))
985-
print("Got response: ")
986-
print("-------------")
987-
print(" {}".format(data))
988-
print("-------------")
974+
logger.error("Could not get exchangeTimezoneName for ticker '{}' reason: {}".format(self.ticker, err))
975+
logger.debug("Got response: ")
976+
logger.debug("-------------")
977+
logger.debug(" {}".format(data))
978+
logger.debug("-------------")
989979
return None
990980

991981
def get_recommendations(self, proxy=None, as_dict=False):
@@ -1267,7 +1257,7 @@ def get_shares(self, proxy=None, as_dict=False):
12671257

12681258
def get_shares_full(self, start=None, end=None, proxy=None):
12691259
# Process dates
1270-
tz = self._get_ticker_tz(debug_mode=False, proxy=None, timeout=10)
1260+
tz = self._get_ticker_tz(proxy=None, timeout=10)
12711261
dt_now = _pd.Timestamp.utcnow().tz_convert(tz)
12721262
if start is not None:
12731263
start_ts = utils._parse_user_dt(start, tz)
@@ -1453,7 +1443,7 @@ def get_earnings_dates(self, limit=12, proxy=None) -> Optional[pd.DataFrame]:
14531443
dates[cn] = _pd.to_datetime(dates[cn], format="%b %d, %Y, %I %p")
14541444
# - instead of attempting decoding of ambiguous timezone abbreviation, just use 'info':
14551445
self._quote.proxy = proxy
1456-
tz = self._get_ticker_tz(debug_mode=False, proxy=proxy, timeout=30)
1446+
tz = self._get_ticker_tz(proxy=proxy, timeout=30)
14571447
dates[cn] = dates[cn].dt.tz_localize(tz)
14581448

14591449
dates = dates.set_index("Earnings Date")

yfinance/multi.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from __future__ import print_function
2323

2424
import logging
25+
import traceback
2526
import time as _time
2627
import multitasking as _multitasking
2728
import pandas as _pd
@@ -117,6 +118,11 @@ def download(tickers, start=None, end=None, actions=False, threads=True, ignore_
117118
shared._DFS = {}
118119
shared._ERRORS = {}
119120

121+
# temporarily disable error reporting while downloading
122+
yf_logger = logging.getLogger('yfinance')
123+
yf_lvl = yf_logger.level
124+
yf_logger.setLevel(logging.CRITICAL)
125+
120126
# download using threads
121127
if threads:
122128
if threads is True:
@@ -148,6 +154,9 @@ def download(tickers, start=None, end=None, actions=False, threads=True, ignore_
148154
if progress:
149155
shared._PROGRESS_BAR.completed()
150156

157+
# restore error reporting
158+
yf_logger.setLevel(yf_lvl)
159+
151160
if shared._ERRORS:
152161
if show_errors:
153162
print('\n%.f Failed download%s:' % (
@@ -222,7 +231,7 @@ def _download_one_threaded(ticker, start=None, end=None,
222231
except Exception as e:
223232
# glob try/except needed as current thead implementation breaks if exception is raised.
224233
shared._DFS[ticker] = utils.empty_df()
225-
shared._ERRORS[ticker] = repr(e)
234+
shared._ERRORS[ticker] = traceback.format_exc()
226235
else:
227236
shared._DFS[ticker.upper()] = data
228237
if progress:
@@ -240,5 +249,5 @@ def _download_one(ticker, start=None, end=None,
240249
actions=actions, auto_adjust=auto_adjust,
241250
back_adjust=back_adjust, repair=repair, proxy=proxy,
242251
rounding=rounding, keepna=keepna, timeout=timeout,
243-
debug=False, raise_errors=False # debug and raise_errors false to not log and raise errors in threads
252+
raise_errors=False # stop individual threads raising errors
244253
)

0 commit comments

Comments
 (0)