1

Suppose I have a function and, depending on its inputs, it must "advise" the caller function that something went wrong:

def get_task(msg, chat):
    task_id = int(msg)
    query = db.SESSION.query(Task).filter_by(id=task_id, chat=chat)
    try:
        task = query.one()
    except sqlalchemy.orm.exc.NoResultFound:
        return "_404_ error"
    return task

Notice at the except block I want to pass something that the caller function can handle and stop its execution if it's necessary, otherwise, it will return the right object.

def something_with_the_task(msg, chat):
   task = get_task(msg, chat)
   if task == "_404_ error":
       return
   #do some stuff with task
2
  • 5
    You should raise an exception and catch it in the caller function. Commented Apr 30, 2018 at 15:22
  • 1
    Define a higher-level more appropriate exception for your interface and raise it, given you have no way to recover from the lower-level failure. Commented Apr 30, 2018 at 15:24

1 Answer 1

3

You already seem to know how exceptions work.

The best thing to do in case of an error is to raise an exception.

Returning some magic value is considered a bad practice, because it requires the caller to explicitly check for it, and a hundred of other reasons.

You can simply let the sqlalchemy.orm.exc.NoResultFound exception escape (by removing the try: and the except: block in get_task()), and let the caller handle it with a try: ... except: ... block, or, if you prefer to do some hiding, you can define a custom exception:

class YourException(Exception):
    pass

and use it like this:

def get_task(msg, chat):
    try:
        task = ...
    except sqlalchemy.orm.exc.NoResultFound:
        raise YourException('explanation')
    return task

def something_with_the_task(msg, chat):
    try:
        task = get_task(msg, chat)
        # do some stuff with task
    except YourException as e:
        # do something with e
        # e.args[0] will contain 'explanation'

Feel free to make the YourException class more informative by explicitly adding some attributes and a constructor to set those, if needed.

The default constructor makes a decent job however:

>>> e = YourException('Program made a boo boo', 42, 'FATAL')
>>> e
YourException('Program made a boo boo', 42, 'FATAL')
>>> e.args[0]
'Program made a boo boo'
>>> e.args[1]
42
>>> e.args[2]
'FATAL'
Sign up to request clarification or add additional context in comments.

1 Comment

You could also use except sqlalchemy.orm.exc.NoResultFound as err: raise YourException('explanation') from err to include the original exception in the traceback.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.