bgenchel
bgenchel

Reputation: 4049

try/except not catching a specific type of exception

I'm trying to catch a specific type of exception that is thrown inside a function call. I enclosed the function call inside a try/except block where the except block catches the specific exception being thrown. I still get a system fail stack trace for that exception, unless I also include a general catch for all exceptions. On including that block and checking the type of the exception being caught, I see that it is catching the type of exception I wanted to catch in the first block. No idea why this is happening.

Context: working on a google app engine app with webapp2 and ndb. The file functions has an init.py that imports all exceptions from exceptions.py

Mock Code and Structure

utils/functions/exceptions.py

"""
Custom exception types
"""

class InvalidParamsException(Exception):
def __init__(self, msg):
    self.msg = msg

def __str__(self):
    return repr(self.msg)

models/models.py

import os, sys
sys.path.append(os.path.join(os.path.dirname(__file__), ".."))
import utils.functions as func
<-->
class ModelClass(ndb.Model):

    @classmethod
    def new(cls):
         <-->
         raise func.InvalidParamsException("Invalid Params to function!")
         <-->

routes.py

import utils.functions as func
from models import ModelClass

class ModelClassHandler(webapp2.RequestHandler):
    def post(self):
        try:
            new_model = ModelClass.new()
        except func.InvalidParamsException as e:
            logging.debug("Caught the right Exception!!")
        except Exception as e:
            logging.debug(":(")
            logging.debug("EXCEPTION TYPE - %s"%str(type(e)))

The output that I get if I don't include that second general except block is:

Traceback (most recent call last):
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1535, in __call__
  rv = self.handle_exception(request, response, e)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1529, in __call__
  rv = self.router.dispatch(request, response)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1278, in default_dispatcher
  return route.handler_adapter(request, response)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1102, in __call__
  return handler.dispatch()
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 572, in dispatch
  return self.handle_exception(e, self.app.debug)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 570, in dispatch
  return method(*args, **kwargs)
File "{{my_path}}/routes.py", line 58, in post
  new_model = ModelClass.new()
File "{{my_path}}/models/models.py", line 559, in new
  raise func.InvalidParamsException("Invalid Params to function!")
InvalidParamsException: 'Invalid Params to function!'

If I do include that second block, I pass the route/function gracefully, and see this in the logs:

DEBUG    2016-03-25 01:01:03,221 routes.py:66] EXCEPTION TYPE - <class 'utils.functions.exceptions.InvalidParamsException'>

Help/Guidance much appreciated!!

Upvotes: 5

Views: 4871

Answers (1)

Jos&#233; Fonseca
Jos&#233; Fonseca

Reputation: 319

It appears that Python raises exceptions as imported in the current namespace. My best evicende for that is the fact that the last line of the traceback calls the raised exception "InvalidParamsException" and not "somemodule.InvalidParamsException".

Thereby, I would suggest resolving the namespace conflicts importing explicitly the exception into the namespace of "routes.py":

from utils.functions.exceptions import InvalidParamsException

and catching the exception by its now-resolved namespace name:

except InvalidParamsException as inv_param_exp: <...>

Upvotes: 5

Related Questions