VFR292
VFR292

Reputation: 109

How to handle chained errors?

I'm running this code which calls yFinance:

try:
    allocation['Price_Data_Cut'], allocation['Price_Current'], allocation['Ticker_CHK'] = zip(*allocation['ETF'].\
        apply(ticker_info, 1, args = (data_cut_datetime,)))
except (SSLError, MaxRetryError, SSLCertVerificationError) as e:
    display('SSL Related Error, prices not fetched')
    pass

I'm getting this output:

---------------------------------------------------------------------------
SSLCertVerificationError                  Traceback (most recent call last)
~/Documents/Python/Investing_Analysis/venv_investing_analysis/lib/python3.8/site-packages/urllib3/connectionpool.py in urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw)
    669             # Make the request on the httplib connection object.
--> 670             httplib_response = self._make_request(
    671                 conn,

~/Documents/Python/Investing_Analysis/venv_investing_analysis/lib/python3.8/site-packages/urllib3/connectionpool.py in _make_request(self, conn, method, url, timeout, chunked, **httplib_request_kw)
    380         try:
--> 381             self._validate_conn(conn)
    382         except (SocketTimeout, BaseSSLError) as e:

~/Documents/Python/Investing_Analysis/venv_investing_analysis/lib/python3.8/site-packages/urllib3/connectionpool.py in _validate_conn(self, conn)
    977         if not getattr(conn, "sock", None):  # AppEngine might not have  `.sock`
--> 978             conn.connect()
    979 

~/Documents/Python/Investing_Analysis/venv_investing_analysis/lib/python3.8/site-packages/urllib3/connection.py in connect(self)
    361 
--> 362         self.sock = ssl_wrap_socket(
    363             sock=conn,

~/Documents/Python/Investing_Analysis/venv_investing_analysis/lib/python3.8/site-packages/urllib3/util/ssl_.py in ssl_wrap_socket(sock, keyfile, certfile, cert_reqs, ca_certs, server_hostname, ssl_version, ciphers, ssl_context, ca_cert_dir, key_password, ca_cert_data)
    383         if HAS_SNI and server_hostname is not None:
--> 384             return context.wrap_socket(sock, server_hostname=server_hostname)
    385 

/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/ssl.py in wrap_socket(self, sock, server_side, do_handshake_on_connect, suppress_ragged_eofs, server_hostname, session)
    499         # ctx._wrap_socket()
--> 500         return self.sslsocket_class._create(
    501             sock=sock,

/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/ssl.py in _create(cls, sock, server_side, do_handshake_on_connect, suppress_ragged_eofs, server_hostname, context, session)
   1039                         raise ValueError("do_handshake_on_connect should not be specified for non-blocking sockets")
-> 1040                     self.do_handshake()
   1041             except (OSError, ValueError):

/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/ssl.py in do_handshake(self, block)
   1308                 self.settimeout(None)
-> 1309             self._sslobj.do_handshake()
   1310         finally:

SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1123)

During handling of the above exception, another exception occurred:

MaxRetryError                             Traceback (most recent call last)
~/Documents/Python/Investing_Analysis/venv_investing_analysis/lib/python3.8/site-packages/requests/adapters.py in send(self, request, stream, timeout, verify, cert, proxies)
    438             if not chunked:
--> 439                 resp = conn.urlopen(
    440                     method=request.method,

~/Documents/Python/Investing_Analysis/venv_investing_analysis/lib/python3.8/site-packages/urllib3/connectionpool.py in urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw)
    725 
--> 726             retries = retries.increment(
    727                 method, url, error=e, _pool=self, _stacktrace=sys.exc_info()[2]

~/Documents/Python/Investing_Analysis/venv_investing_analysis/lib/python3.8/site-packages/urllib3/util/retry.py in increment(self, method, url, response, error, _pool, _stacktrace)
    438         if new_retry.is_exhausted():
--> 439             raise MaxRetryError(_pool, url, error or ResponseError(cause))
    440 

MaxRetryError: HTTPSConnectionPool(host='query2.finance.yahoo.com', port=443): Max retries exceeded with url: /v8/finance/chart/SPY?period1=1684735200&period2=1685685600&interval=1d&includePrePost=False&events=div%2Csplits (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1123)')))

During handling of the above exception, another exception occurred:

SSLError                                  Traceback (most recent call last)
<ipython-input-118-4ca34707d1d0> in <module>
     25 
     26 try:
---> 27     allocation['Price_Data_Cut'], allocation['Price_Current'], allocation['Ticker_CHK'] = zip(*allocation['ETF'].\
     28         apply(ticker_info, 1, args = (data_cut_datetime,)))
     29 except (SSLError, MaxRetryError, SSLCertVerificationError) as e:

~/Documents/Python/Investing_Analysis/venv_investing_analysis/lib/python3.8/site-packages/pandas/core/series.py in apply(self, func, convert_dtype, args, **kwds)
   4198             else:
   4199                 values = self.astype(object)._values
-> 4200                 mapped = lib.map_infer(values, f, convert=convert_dtype)
   4201 
   4202         if len(mapped) and isinstance(mapped[0], Series):

pandas/_libs/lib.pyx in pandas._libs.lib.map_infer()

~/Documents/Python/Investing_Analysis/venv_investing_analysis/lib/python3.8/site-packages/pandas/core/series.py in f(x)
   4183 
   4184             def f(x):
-> 4185                 return func(x, *args, **kwds)
   4186 
   4187         else:

<ipython-input-118-4ca34707d1d0> in ticker_info(tickerSymbol, data_cut_datetime)
      8     tickerData = yf.Ticker(tickerSymbol)
      9 #     print(tickerData)
---> 10     prices = tickerData.history(period='1d', start=data_cut_datetime.strftime("%Y-%m-%d"), 
     11             end=(datetime.now() + timedelta(days = 1)).strftime("%Y-%m-%d"))
     12 

~/Documents/Python/Investing_Analysis/venv_investing_analysis/lib/python3.8/site-packages/yfinance/base.py in history(self, period, interval, start, end, prepost, actions, auto_adjust, back_adjust, proxy, rounding, tz, **kwargs)
    150         # Getting data from json
    151         url = "{}/v8/finance/chart/{}".format(self._base_url, self.ticker)
--> 152         data = self.session.get(
    153             url=url,
    154             params=params,

~/Documents/Python/Investing_Analysis/venv_investing_analysis/lib/python3.8/site-packages/requests/api.py in get(url, params, **kwargs)
     74 
     75     kwargs.setdefault('allow_redirects', True)
---> 76     return request('get', url, params=params, **kwargs)
     77 
     78 

~/Documents/Python/Investing_Analysis/venv_investing_analysis/lib/python3.8/site-packages/requests/api.py in request(method, url, **kwargs)
     59     # cases, and look like a memory leak in others.
     60     with sessions.Session() as session:
---> 61         return session.request(method=method, url=url, **kwargs)
     62 
     63 

~/Documents/Python/Investing_Analysis/venv_investing_analysis/lib/python3.8/site-packages/requests/sessions.py in request(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)
    528         }
    529         send_kwargs.update(settings)
--> 530         resp = self.send(prep, **send_kwargs)
    531 
    532         return resp

~/Documents/Python/Investing_Analysis/venv_investing_analysis/lib/python3.8/site-packages/requests/sessions.py in send(self, request, **kwargs)
    641 
    642         # Send the request
--> 643         r = adapter.send(request, **kwargs)
    644 
    645         # Total elapsed time of the request (approximately)

~/Documents/Python/Investing_Analysis/venv_investing_analysis/lib/python3.8/site-packages/requests/adapters.py in send(self, request, stream, timeout, verify, cert, proxies)
    512             if isinstance(e.reason, _SSLError):
    513                 # This branch is for urllib3 v1.22 and later.
--> 514                 raise SSLError(e, request=request)
    515 
    516             raise ConnectionError(e, request=request)

SSLError: HTTPSConnectionPool(host='query2.finance.yahoo.com', port=443): Max retries exceeded with url: /v8/finance/chart/SPY?period1=1684735200&period2=1685685600&interval=1d&includePrePost=False&events=div%2Csplits (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1123)')))

Why isn't my except statement catching this error? What should I do to catch this using something more granular than except Exception (note except Exception does work)?

I've read the documentation Here and tried changing the order of the errors in the except statement, but I can't seem to figure this out.

Upvotes: 0

Views: 97

Answers (3)

VFR292
VFR292

Reputation: 109

As per a comment from @NYC Coder

I needed to use from requests.exceptions import SSLError as requests_SSLError

When I did that except (requests_SSLError) as e worked.

Upvotes: 0

John Gordon
John Gordon

Reputation: 33343

The traceback message contains this section:

     25 
     26 try:
---> 27     allocation['Price_Data_Cut'], allocation['Price_Current'], allocation['Ticker_CHK'] = zip(*allocation['ETF'].\
     28         apply(ticker_info, 1, args = (data_cut_datetime,)))
     29 except SSLCertVerificationError as e:

This does not match the code you posted. Therefore the error is happening in some other part of your code that you did not show us.

Upvotes: 1

Saxtheowl
Saxtheowl

Reputation: 4658

Python will only catches the final exception type that is raised, not any intermediate exceptions, you have to include MaxRetryError in your except, also if you want to handle the SSLError when it is wrapped in a MaxRetryError, we have to add an additional check.

from requests.exceptions import SSLError
from urllib3.exceptions import MaxRetryError
from ssl import SSLCertVerificationError

def ticker_info(tickerSymbol, data_cut_datetime):
    # This function should contain your code that might raise the SSLError, MaxRetryError or SSLCertVerificationError

try:
    allocation['Price_Data_Cut'], allocation['Price_Current'], allocation['Ticker_CHK'] = zip(*allocation['ETF'].\
        apply(ticker_info, 1, args = (data_cut_datetime,)))
except (MaxRetryError, SSLCertVerificationError) as e:
    if isinstance(e.reason, SSLError):
        display('SSL Related Error, prices not fetched')
    else:
        display('Max Retry Error, prices not fetched')
    pass
except SSLError as e:
    display('SSL Related Error, prices not fetched')
    pass

Upvotes: 1

Related Questions