I have a python flask app, pseudocode shown below.
#app.route('/predict', methods=['POST'])
def transformation():
try:
var1 = function_1()
# do something with var1
var2 = function_2()
except Exception as e:
return jsonify({'message': '{}: {}'.format(type(e).__name__, e)}), 500
As you see, the POST call handler returns a generic exception message back to the client. But I want to customize those exception messages based on whether they are coming from function_1 or function_2
I looked into this thread and understand that it is possible to do below -
try:
#something1
#something2
except ExceptionType1:
#return xyz
except ExceptionType2:
#return abc
But how would it know that ExceptionType1 is coming from function_1() or function_2(). How should I pass exception from function_1() or function_2() to be caught in the main try-except block?
Related
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 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
I am trying to create the following exception and call it in another function:
### The exception
class GoogleAuthError(Exception):
def __init__(self, message, code=403):
self.code = code
self.message = message
### Generating the exception
raise GoogleAuthError(message="There was an error authenticating")
### printing the exception
try:
do_something()
except GoogleAuthError as e:
print(e.message)
Basically, I want it to print "There was an error authenticating". How would I do this properly, or is the above the correct way to do it?
Remove the code argument from your __init__. You aren't using it.
You can also delegate the handling of the error message to the parent Exception class, which already knows about messages
class GoogleAuthError(Exception):
def __init__(self, message):
super().__init__(message)
self.code = 403
try:
raise GoogleAuthError('There was an error authenticating')
except GoogleAuthError as e:
print(e)
# There was an error authenticating
I'm using pynic framework to handle my APIs endpoints, but I guess this would be the same logic with Flask or Django.
I've got a few endpoints, and I was wondering if there were anyway to handle all the exceptions at the same place.
For instance:
class Pnorm(Handler):
def post(self):
logger = logging.getLogger(constants.loggerName)
template_exception = "Exception {0} in class {1} ({2})."
try:
myJson = DoThings()
return myJson
except HTTP_400 as e:
logger.critical(message)
raise e
except Exception as e:
# unknown exception raise 500
logger.critical(message)
raise HTTP_500(message)
Is there anyway I can make all my endpoints handle the exceptions the same way or do I hacve to repeat my "exception block" at the end of each point ?
(I don't mean in the same class only but through the project.)
Cheers,
Julien
Edited:
My main class:
class app(WSGI):
DataStructureHelper.set_dsh()
setup_logging.setup_logging(logger_name=constants.loggerName, console_level=logging.INFO)
routes = [
('/allocator', Allocator()),
('/data/([0-9]+)/([0-9]+)/([0-9]+)/([0-9]+)', InstrumentData()),
('/pnorm', Pnorm()),
('/portfolios')
]
I think the right approach would be decorators, since it fits the needs perfectly. Following is working piece of code w.r.t flask.
A word of caution is you need return the control back to handlers from decorator.
from functools import wraps
from flask import Flask, request
app = Flask(__name__)
def http_error_codes(method_name):
#wraps(method_name)
def handle_exceptions(*args):
try:
print("Inside the exceptions")
return method_name(*args)
except Exception as e:
print("HAHAHAHA")
raise e
return handle_exceptions
def do_the_login():
return "Testing is fun"
def show_the_login_form():
raise ValueError('The day is too frabjous.')
#app.route('/login', methods=['GET', 'POST'])
#http_error_codes
def login():
if request.method == 'POST':
return do_the_login()
else:
return show_the_login_form()
if __name__ == '__main__':
app.run()
Hope this helps
If you want to handle all the exceptions in a single place, you can keep an general exceptional block like as follows..
try:
#Code part may give error
except Exception:
#If error what to do..
Here Exception is the General class, which will handle all exceptions irrespective of the error.
Given this simple Bottle code:
def bar(i):
if i%2 == 0:
return i
raise MyError
#route('/foo')
def foo():
try:
return bar()
except MyError as e:
response.status_code = e.pop('status_code')
return e
How would one write Bottle middleware so the same exception handling is done implicitly, so that code like this can work identically to above:
#route('/foo')
def foo():
return bar()
You can do this elegantly with a plugin leveraging abort:
from bottle import abort
def error_translation(func):
def wrapper(*args,**kwargs):
try:
func(*args,**kwargs)
except ValueError as e:
abort(400, e.message)
return wrapper
app.install(error_translation)
Bottle respect the wsgi spec. You can use a classic wsgi middleware
from bottle import route, default_app, run, request
# push an application in the AppStack
default_app.push()
#route('/foo')
def foo():
raise KeyError()
# error view
#route('/error')
def error():
return 'Sorry an error occured %(myapp.error)r' % request.environ
# get the bottle application. can be a Bottle() instance too
app = default_app.pop()
app.catchall = False
def error_catcher(environ, start_response):
# maybe better to fake the start_response callable but this work
try:
return app.wsgi(environ, start_response)
except Exception as e:
# redirect to the error view if an exception is raised
environ['PATH_INFO'] = '/error'
environ['myapp.error'] = e
return app.wsgi(environ, start_response)
# serve the middleware instead of the applicatio
run(app=error_catcher)
You can use this instead:
from bottle import error, run, route
#error(500)
def error_handler_500(error):
return json.dumps({"status": "error", "message": str(error.exception)})
#route("/")
def index():
a = {}
a['aaa']
run()