跨应用程序处理来自外部 API 的网络错误

Handling network errors from an external API across an application

我的应用严重依赖于外部 API (last.fm),它使用 python 包装器 pylast

但是网络容易出现一些不稳定的情况,一旦网络连接失败,一切都会崩溃。

这样的网络配置在 project/config.py:

class DevelopmentConfig(BaseConfig):    
    # LastFm credentials
    LASTFM_API_KEY = "mykey"
    LASTFM_API_SECRET = "mysecret"
    LASTFM_USERNAME = "myusername"
    LASTFM_PWD_HASH = "fEl@O5R$#^GFIbij1"

并在 tags.py 初始化,如下所示:

from project.config import DevelopmentConfig

last = pylast.LastFMNetwork(
    api_key = DevelopmentConfig.LASTFM_API_KEY, 
    api_secret =DevelopmentConfig.LASTFM_API_SECRET, 
    username = DevelopmentConfig.LASTFM_USERNAME, 
    password_hash = pylast.md5(DevelopmentConfig.LASTFM_PWD_HASH))

如何保护我的应用程序并处理如下所示的错误,以便应用程序不会在网络连接失败时中断?

完整日志回溯:

Traceback (most recent call last):
   File "/usr/lib/python3.6/site-packages/pylast/__init__.py", line 843, in _download_response
     method='POST', url=HOST_SUBDIR, body=data, headers=headers)
   File "/usr/lib/python3.6/http/client.py", line 1239, in request
     self._send_request(method, url, body, headers, encode_chunked)
   File "/usr/lib/python3.6/http/client.py", line 1285, in _send_request
     self.endheaders(body, encode_chunked=encode_chunked)
   File "/usr/lib/python3.6/http/client.py", line 1234, in endheaders
     self._send_output(message_body, encode_chunked=encode_chunked)
   File "/usr/lib/python3.6/http/client.py", line 1026, in _send_output
     self.send(msg)
   File "/usr/lib/python3.6/http/client.py", line 964, in send
     self.connect()
   File "/usr/lib/python3.6/http/client.py", line 1392, in connect
     super().connect()
   File "/usr/lib/python3.6/http/client.py", line 936, in connect
     (self.host,self.port), self.timeout, self.source_address)
   File "/usr/lib/python3.6/socket.py", line 704, in create_connection
     for res in getaddrinfo(host, port, 0, SOCK_STREAM):
   File "/usr/lib/python3.6/socket.py", line 745, in getaddrinfo
     for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
 socket.gaierror: [Errno -2] Name does not resolve

 During handling of the above exception, another exception occurred:

 Traceback (most recent call last):
   File "/usr/src/app/manage.py", line 28, in <module>
     app = create_app()  
   File "/usr/src/app/project/__init__.py", line 27, in create_app
     from .api import routes, models
   File "/usr/src/app/project/api/routes/__init__.py", line 2, in <module>
     from .register import register_bp
   File "/usr/src/app/project/api/routes/register.py", line 7, in <module>
     from project.api.classifiers.rec_pipeline.charts import project
   File "/usr/src/app/project/api/classifiers/rec_pipeline/charts.py", line 2, in <module>
     from .collab import collab_filter
   File "/usr/src/app/project/api/classifiers/rec_pipeline/collab.py", line 6, in <module>
     from project.api.models.methods import Collaborative_Filtering
   File "/usr/src/app/project/api/models/methods.py", line 14, in <module>
     from project.api.resources.genius import lyrics
   File "/usr/src/app/project/api/resources/genius/lyrics.py", line 21, in <module>
     from project.api.resources.lastfm.seeds.tags import *
   File "/usr/src/app/project/api/resources/lastfm/seeds/tags.py", line 15, in <module>
     password_hash = pylast.md5(DevelopmentConfig.LASTFM_PWD_HASH))
   File "/usr/lib/python3.6/site-packages/pylast/__init__.py", line 636, in __init__
     "user": "user/%(name)s",
   File "/usr/lib/python3.6/site-packages/pylast/__init__.py", line 177, in __init__
     self.username, self.password_hash)
   File "/usr/lib/python3.6/site-packages/pylast/__init__.py", line 982, in get_session_key
     doc = request.execute()
   File "/usr/lib/python3.6/site-packages/pylast/__init__.py", line 862, in execute
     response = self._download_response()
   File "/usr/lib/python3.6/site-packages/pylast/__init__.py", line 845, in _download_response
     raise NetworkError(self.network, e)
 pylast.NetworkError: NetworkError: [Errno -2] Name does not resolve

编辑:

根据下面的评论,到目前为止我正在尝试:

try:
    last = pylast.LastFMNetwork(
        api_key = DevelopmentConfig.LASTFM_API_KEY, 
        api_secret =DevelopmentConfig.LASTFM_API_SECRET, 
        username = DevelopmentConfig.LASTFM_USERNAME, 
        password_hash = pylast.md5(DevelopmentConfig.LASTFM_PWD_HASH))
except socket.gaierror as e:
    print (e)

但我不知道这是更稳定还是更可靠的解决方案。

你可以这样做:

attempts = 3
while attempts > 0:
    try:
        attempts = attempts - 1
        do_network_stuff
    except exception as e:  # those you wish to handle
        print(e)  # or more graceful handling