如何处理链式错误?

huangapple go评论61阅读模式
英文:

How to handle chained errors?

问题

我正在运行调用yFinance的这段代码

```python
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相关错误,无法获取价格')
    pass

我得到了以下输出:

---------------------------------------------------------------------------
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

<details>
<summary>英文:</summary>

I&#39;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&#39;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&#39;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&#39;ve read the documentation [Here][1] and tried changing the order of the errors in the except statement, but I can&#39;t seem to figure this out.
[1]: https://docs.python.org/3/tutorial/errors.html#handling-exceptions
</details>
# 答案1
**得分**: 1
Python只会捕获引发的最终异常类型,而不会捕获任何中间异常,您必须在except中包括`MaxRetryError`,同时如果您想在它被包装在`MaxRetryError`中时处理`SSLError`,我们必须添加额外的检查。
```python
from requests.exceptions import SSLError
from urllib3.exceptions import MaxRetryError
from ssl import SSLCertVerificationError
def ticker_info(tickerSymbol, data_cut_datetime):
# 此函数应包含可能引发SSLError、MaxRetryError或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相关错误,未获取价格')
else:
display('最大重试错误,未获取价格')
pass
except SSLError as e:
display('SSL相关错误,未获取价格')
pass

如果您需要进一步的翻译或有其他问题,请告诉我。

英文:

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[&#39;Price_Data_Cut&#39;], allocation[&#39;Price_Current&#39;], allocation[&#39;Ticker_CHK&#39;] = zip(*allocation[&#39;ETF&#39;].\
apply(ticker_info, 1, args = (data_cut_datetime,)))
except (MaxRetryError, SSLCertVerificationError) as e:
if isinstance(e.reason, SSLError):
display(&#39;SSL Related Error, prices not fetched&#39;)
else:
display(&#39;Max Retry Error, prices not fetched&#39;)
pass
except SSLError as e:
display(&#39;SSL Related Error, prices not fetched&#39;)
pass

答案2

得分: 1

跟踪消息包含以下部分:

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

这与您发布的代码不匹配。因此,错误发生在您未向我们展示的代码的其他部分。

英文:

The traceback message contains this section:

     25 
26 try:
---&gt; 27     allocation[&#39;Price_Data_Cut&#39;], allocation[&#39;Price_Current&#39;], allocation[&#39;Ticker_CHK&#39;] = zip(*allocation[&#39;ETF&#39;].\
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.

答案3

得分: 0

根据@NYC Coder评论

我需要使用from requests.exceptions import SSLError as requests_SSLError

当我这样做时,except (requests_SSLError) as e起作用。

英文:

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.

huangapple
  • 本文由 发表于 2023年6月2日 01:46:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76384446.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定