My app depends heavily on an external API (last.fm
), for which it uses a python wrapper, pylast
.
The network is prone to some instability, however, and when network connection fails, all breaks down.
Such network configuration goes at 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"
and is initialized at tags.py
like so:
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))
How do I protect my app and handle errors like the one below, so the app does not break if network connection fails?
Full log traceback:
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
EDIT:
based on the comments below, so far I'm trying:
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)
but I don't know if this is the more stable or reliable solution.
You can do something like this:
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