I am using the following approach for handling Twilio exceptions in Python:
try:
#code for sending the sms
print(message.sid)
except TwilioRestException as e:
print(e)
This allows me to send sms and Exceptions are handled by Python.
Now I need to "return" the exceptions codes in order to process them, let's say, give user a message depending on the exception.
How can I achieve that?
If raising exception is not an option you could simply add return under except block.
def func():
# your logic
try:
#code for sending the sms
print(message.sid)
except TwilioRestException as e:
print(e)
return e.code # or whetever attribute e has for it...
By default function will return None if everything goes right. In client code it will be like
err = func()
if err:
# sms wasn't sent, action required
Related
im making a python script that can manage my google projects.
im having a insue with one part
when i try to exclude the project its can return to me many errors.
i did a peace of code to get this exception:
try:
# Initialize request argument(s)
request = DeleteProjectRequest(
name=project,
)
self.project_manager.delete_project(request=request)
except PermissionDenied as exc:
# GCP returns PermissionDenied whether we actually does
# not have permissions to perform the get_project call
# or when the project does not exist. Due to this reason,
# the PermissionDenied exception catch won't be deterministic.
logger.error(f"Project '{project_id}' does not exist", exc)
return False
i need to get the error message of all types of errors
i changed except PermissionDenied as exc: for except Exception as exc:
and it works but i need to call the logger only if the error is PermissionDenied and in all cases i need to call another function passing the message as parameter like it return_to_db(error_message)
my question is. how can i run only the logger if the error is PermissionDenied?
You can also catch multiple Exceptions by adding additional blocks, though it will choose the first isinstance() match (so if you put Exception first, it will be selected instead, while TypeError would be continued past)
try:
self.project_manager.delete_project(
request=DeleteProjectRequest(name=project))
except PermissionDenied as exc:
# GCP returns PermissionDenied whether we actually does
# not have permissions to perform the get_project call
# or when the project does not exist. Due to this reason,
# the PermissionDenied exception catch won't be deterministic.
logger.error(f"Project '{project_id}' does not exist", exc)
except Exception:
# FIXME other handling to go here
pass # fall to return False
else: # didn't raise
return True
# opportunity for finally: block here too
# if any Exception was raised, continue to return False
return False
You can add a condition of the instance type of the current exception in Python, example :
try:
# Initialize request argument(s)
request = DeleteProjectRequest(
name=project,
)
self.project_manager.delete_project(request=request)
except Exception as exc:
if isinstance(exc, PermissionDenied):
logger.error(f"Project '{project_id}' does not exist", exc)
return False
As expected, the logger is executed only if the exception instance is PermissionDenied.
I am a newbie in python software development. I have created a script which includes many functions returning output of a request and handling the exceptions generated by them. One of the func. is as below:
def ApiResponse(emailHash):
r=None
errorMessage = ""
url = "https://dummy.com"
try:
r = requests.get(url, timeout = TIMEOUT_LIMIT)
except requests.exceptions.Timeout as e:
errorMessage = "Timeout Error"
except requests.ConnectionError as e:
errorMessage = "ConnectionError"
except requests.RequestException as e:
errorMessage = "Some other Request Exception"
return r
I have many such functions returning response for different requests. But, they all repeat the exception handling code. I want to handle exceptions separately in another function so that I don't have to repeat myself. I have tried stuff like passing on the variable "e" to other function and comparing it to the exception types and return different error messages accordingly but I cant seem to compare, lets say, e == requests.exceptions.Timeout.
What else can i do just to separate out that exception handling part? I aim to write a modular code!
You can use exception-decouple package for good readbility:
from exception_decouple import redirect_exceptions
def timeout_handler(emailHash, e):
return "Timeout Error"
def default_handler(emailHash, e):
return "Other Error"
#redirect_exceptions(timeout_handler, requests.exceptions.Timeout)
#redirect_exceptions(default_handler, requests.ConnectionError,
requests.RequestException)
def ApiResponse(emailHash):
r=None
url = "https://dummy.com"
r = requests.get(url, timeout = TIMEOUT_LIMIT)
return r
one of the ways I found was to compare the type of the error with the error. for example in the above case.
def exception_handler(e):
if type(e) is requests.exceptions.ConnectTimeout:
return "Timeout Error"
elif type(e) is requests.ConnectionError:
return "ConnectionError"
else:
return "Some other Request Exception"
this should work
I've been given some web scraping code on Python and now need to write some code so that if there is an error, it will notify someone by email. I have found this code online:
def send_email():
to = request.form.get('to')
if not to:
return ('Please provide an email address in the "to" query string '
'parameter.'), 400
sg = sendgrid.SendGridAPIClient(apikey=SENDGRID_API_KEY)
to_email = mail.Email(to)
from_email = mail.Email(SENDGRID_SENDER)
subject = 'This is a test email'
content = mail.Content('text/plain', 'Example message.')
message = mail.Mail(from_email, subject, to_email, content)
response = sg.client.mail.send.post(request_body=message.get())
if response.status_code != 202:
return 'An error occurred: {}'.format(response.body), 500
return 'Email sent.'
Is this the kind of thing that I should use? If not, what is the best way to go about this problem?
Thanks in advance.
What I meant:
try:
# Web scrapping code
except requests.packages.urllib3.exceptions.MaxRetryError as e:
print repr(e)
send_email()
OR
use except without specifying for passive handling.
try:
# Web scrapping code
except:
send_email()
BUT:
From the PEP-8 Style Guide for Python:
When catching exceptions, mention specific exceptions whenever
possible instead of using a bare except: clause.
A bare except: clause will catch SystemExit and KeyboardInterrupt
exceptions, making it harder to interrupt a program with Control-C,
and can disguise other problems. If you want to catch all exceptions
that signal program errors, use except Exception: (bare except is
equivalent to except BaseException:).
A good rule of thumb is to limit use of bare 'except' clauses to two
cases:
If the exception handler will be printing out or logging the
traceback; at least the user will be aware that an error has occurred.
If the code needs to do some cleanup work, but then lets the exception
propagate upwards with raise. try...finally can be a better way to
handle this case.
If i have some bad authorization data (for example wrong password) SUDS rises exception (400, u'Bad Request') from which i cant get anything, but in teh log is response, which contains data that password is wrong, but how to get this response? I tried like this:
except Exception as e:
print str(e)
print self._client.last_received()
It prints:
(400, u'Bad Request')
None
But in log there is long xml which contains <SOAP-ENV:Reason><SOAP-ENV:Text xml:lang="en">Sender not authorized</SOAP-ENV:Text></SOAP-ENV:Reason>
I am pulling this out of a comment and into an answer because of the code block.
import suds.client
try:
auth_url = "https://url.to.my.service/authenticator?wsdl"
auth_client = suds.client.Client(auth_url)
cookie = auth_client.service.authenticate(user,password)
except Exception as e:
print str(e)
print auth_client.last_received()
Using this code, I receive the appropriate response from my service if I pass an invalid password:
Server raised fault: 'error.pwd.incorrect'
None
And an appropriate response if I pass an invalid user id:
Server raised fault: 'error.uid.missing'
None
Something you may want to consider doing, is changing your except statement to catch suds.WebFault instead of the generic exception. There may be something else that is occurring and triggering your exception block.
One other thing that may help with your issue, is to pass faults=True in your Client() call.
The Client can be configured to throw web faults as WebFault or to
return a tuple (, )
The code I posted above would look like this:
auth_client = suds.client.Client(auth_url, faults=True)
When I have two Python exceptions that are the same exception class but a different error message, how do I catch them separately?
For specific use-case:
I'm using the Facepy library to hit the Facebook Graph API. When the API returns an error that isn't Oauth related, Facepy raises a facepy.exceptions.FacebookError and passes the error message given by the Facebook API.
I'm consistently hitting two different errors that I'd like to treat differently and the only way to parse them is the error message, but I can't figure out how to write my except clause--here it is in pseudo-code:
try:
#api query
except facepy.exceptions.OAuthError and error_message = 'object does not exist':
# do something
except facepy.exceptions.OAuthError and error_message = 'Hit API rate limit':
# do something else
How do I write these except clauses to trigger off both the exception and the error message?
Assuming the Exception's error message is in the error_message attribute (it may be something else — look at the Exception's __dict__ or source to find out):
try:
#api query
except facepy.exceptions.OAuthError as e:
if e.error_message == "object does not exist":
print "Do X"
elif e.error_message == "Hit API rate limit":
print "Do Y"
else:
raise
facepy's OAuthError derives from FacebookError and that has message attribute. https://github.com/jgorset/facepy/blob/master/facepy/exceptions.py#L8. So, you can use if condition with the message like this
try:
#api query
except facepy.exceptions.OAuthError as error:
if 'object does not exist' == error.message:
# do something
elif 'Hit API rate limit' == error.message:
# do something else
else:
raise