How many try/except is too many in python function - python

I have a function that geocodes an address. I don't want this function to die so I am trying to catch the error and return a tuple instead.
However I also want to differentiate between errors, for this I use try/except in multiple places.
Is there such a thing as too many try/except? How would you optimize this function?
Here is my code:
def geocode(address):
js = ''
try:
urlq = urllib.urlencode({'address':address, 'sensor':'false'})
except Exception, e:
return (False, "Error url-encoding address. Error:%s" % e, js, 'failed')
try:
f = urllib2.urlopen(GEO_URL + urlq)
d = f.read()
except Exception, e:
return (False, "Error making connection. Error:%s" % e, js, 'failed')
#
try:
js = json.loads(d)
except Exception, e:
return (False, "Error converting JSON. Error:%s" % e, js, 'failed')
return (True, '', js, 'ok')

Catching Exception is always a bad idea. You want to specify which error you want to catch.
try:
...
except URLError, e:
return (False, "Error making connection. Error:%s" % e, js, 'failed')
except ValueError, e:
return (False, "Error converting JSON. Error:%s" % e, js, 'failed')
except UnicodeEncodeError, e:
return (False, "Error unicode formatting. Error:%s" % e, js, 'failed')
Also returning a tuple to indicate an error is usually not preferred. Consider putting the try except in the calling function and to let the error propagate up.

Related

Python - try except with multiple possibilities

I'm trying the following:
try:
scroll_token = response["scroll_token"]
except ValueError as e:
logging.info(f'could not find "scroll_token" {e}')
try:
scroll_token = response["scroll_id"]
except ValueError as e:
logging.info(f'could not find "scroll_id" {e}')
Pretty much if the response doesn't have "scroll_token" in the response then I want it to see if there is "scroll_id" in the response instead. but for some reason this isn't working, it just keeps failing at the 1st try case and says:
scroll_token = response["scroll_token"] KeyError: 'scroll_token'
You are catching the wrong exception; it's KeyError that you are expecting could be raised.
try:
scroll_token = response["scroll_token"]
except KeyError as e:
logging.info(f'could not find "scroll_token" {e}')
try:
scroll_token = response["scroll_id"]
except KeyError as e:
logging.info(f'could not find "scroll_id" {e}')
You can write this more simply with a loop.
for k in ["scroll_token", "scroll_id"]:
try:
scroll_token = response[k]
break
except KeyError:
logging.info("could not find %s", k)
else:
# What to do if neither key is found?
...

Python requests: Parallel requests using ThreadPoolExecutor

I am using a thread pool to send requests in parallel (generate a list of urls, fetch in parallel, request all of the urls concurrently), parsing some data out of the response to a couple of dicts, cross-mapping keys across dicts and then writing it back to pandas.DataFrame
def fetch_point(point_url):
try:
r = requests.get(point_url, headers=self.headers)
r.raise_for_status()
except requests.exceptions.HTTPError as errh:
logging.error(f'HTTP Error: {errh}')
except requests.exceptions.ConnectionError as errc:
logging.error(f'Connection Error: {errc}')
except requests.exceptions.Timeout as errt:
logging.error(f'Timeout Error: {errt}')
except requests.exceptions.RequestException as e:
logging.error(e)
raise SystemExit(e)
result = r.json().get('data')
# print(result)
building_url = result['building']
return point_url, building_url
def fetch_building(building_url):
try:
r = requests.get(building_url, headers=self.headers)
r.raise_for_status()
except requests.exceptions.HTTPError as errh:
logging.error(f'HTTP Error: {errh}')
except requests.exceptions.ConnectionError as errc:
logging.error(f'Connection Error: {errc}')
except requests.exceptions.Timeout as errt:
logging.error(f'Timeout Error: {errt}')
except requests.exceptions.RequestException as e:
logging.error(e)
raise SystemExit(e)
result = r.json().get('data')
building_name = result['name']
return building_url, building_name
pool = ThreadPoolExecutor()
point_urls = df.loc[~df['Point Url'].isnull(), 'Point Url'].to_list()
building_urls = {}
for point_url, building_url in pool.map(fetch_point, point_urls):
building_urls[point_url] = building_url
building_urls_list = building_urls.values()
building_names = {}
for building_url, building_name in pool.map(fetch_building, building_urls_list):
building_names[building_url] = building_name
point_building_map = {k: building_names[building_urls[k]] for k in building_urls}
for key in point_building_map.keys():
df.loc[df['Point Url'] == key, 'Building'] = point_building_map[key]
I am wondering if there is a more optimized approach I could consider. Should I go for asyncio/aiohttp instead of ThreadPoolExecutor?

I can't catch the proper raise error I am sending(Raising UnicodeDecodeError and getting TypeError)

I am creating a flask application and whenever I am trying to raise a UnicodeDecodeError from the class Validation and returning to my main try block then instead of going to UnicodeDecodeError exception it's going to Exception block
This is my main block from where I am calling my class Validation and expecting a UnicodeDecodeError
try:
validation = Validation(request.files['csvfile'])
validation.checkextension()
# columns = validation.check_columns(csv)
return redirect(request.url)
except UnicodeDecodeError:
# return Response("Error : %s"% UnicodeDecodeError)
return "Please enter a .csv extension"
except Exception as e:
print("abc",repr(e))
# return Response("Error : %s"% Exception)
return "Exception"
This is my class from where i am raising the error:
class Validation:
def __init__(self,file):
self.file = file
self.location = "./uploads/" + str(file.filename)
def checkextension(self):
try:
self.file.save(os.path.join("uploads", self.file.filename))
data = pd.read_csv(self.location)
except UnicodeDecodeError:
os.remove("./uploads/" + str(self.file.filename))
raise UnicodeDecodeError
except Exception:
print(Exception)
raise Exception
Also When I am printing the statement in except Exception as e:
I am getting this output:
TypeError('function takes exactly 5 arguments (0 given)')
I am getting TypeError but I am raising UnicodeDecodeError

python selnium website login except question

The error message is not print
What's the problem? ㅠㅠㅠㅠ
uid = id
upw = pw
try:
driver.find_element_by_xpath('//*[#id="userID"]').send_keys(uid)
action.reset_actions()
driver.find_element_by_xpath('//*[#id="userPWD"]').send_keys(upw)
driver.find_element_by_xpath('//*[#id="btnLogin"]').click()
except Exception as e:
print("{} 계정 로그인이 실패하였습니다.".format(uid))
In order to print the exception, you need to actually print e, not uid:
.....
except Exception as e:
print("{} 계정 로그인이 실패하였습니다.".format(uid))
print(e)

For loop only iterating one object from list using python

For loop only iterating one object from the list provided by the function. Below are the code and terminal logs.
Note:- I want to delete both the URLs which are the part of below list
function delete_index_url() output is like :-
['https://vpc.xxx.es.amazonaws.com/staging-logs-2019.09.13', 'https://vpc.xxx.es.amazonaws.com/staging-logs-2019.09.16']
def clean_index( ):
delete_urls = delete_index_url() # above function output assign to variable
for i in delete_urls:
print(i) <-- this only print "https://vpc.xxx.es.amazonaws.com/staging-logs-2019.09.13"
try:
req = requests.delete(i)
except requests.exceptions.ConnectionError as e:
print ('ERROR: Not able to connect to URL')
return 0
except requests.exceptions.Timeout as e:
print ('ERROR: ElasticSearch time out')
return 0
except requests.exceptions.HTTPError as e:
print ('ERROR: HTTP error')
return 0
else:
print ('INFO: ElasticSearch response status code was %s' % req.status_code)
if req.status_code != 200:
return 0
else:
return 1
print(clean_index())
Logs output from a python script:-
INFO: Sorting indexes
['https://vpc.xxx.es.amazonaws.com/staging-logs-2019.09.13', 'https://vpc.xxx.es.amazonaws.com/staging-logs-2019.09.16']
INFO: Getting a list of indexes
INFO: ElasticSearch response status code was 200
INFO: Found 200 indexes
INFO: Sorting indexes
https://vpc.xxx.es.amazonaws.com/staging-logs-2019.09.13 # only 2019.09.13, not 2019.09.16 logs URLs
Instead of returning 0 or 1 and ending the function right away, you can create a list and store the responses and return it:
def clean_index( ):
responses = []
delete_urls = delete_index_url() # above function output assign to variable
for i in delete_urls:
print(i)
try:
req = requests.delete(i)
except requests.exceptions.ConnectionError as e:
print ('ERROR: Not able to connect to URL')
responses.append(0)
except requests.exceptions.Timeout as e:
print ('ERROR: ElasticSearch time out')
responses.append(0)
except requests.exceptions.HTTPError as e:
print ('ERROR: HTTP error')
responses.append(0)
else:
print ('INFO: ElasticSearch response status code was %s' % req.status_code)
if req.status_code != 200:
responses.append(0)
else:
responses.append(1)
return responses
print(clean_index())

Categories

Resources