2

TL;DR: Why are my exceptions triggering only in certain situations, despite the fact that it is the same error?

The code successfully catches a NameError with an all numerical argument. So if someone mistakenly inputs a number instead of an operator, it gives them the correct exception error message. However, my code fails to catch other exceptions, and I'm unsure why.

For example:

print(better_calc(5, 5, 5))

This returns the desired exception message of

5 5 5 = Error: Name error. Please check your input

However, it does not catch other errors. Instead, it terminates the programme. For example,

print(better_calc(5, g, 5))

This returns ''NameError: name 'g' is not defined'', without triggering the exception or the exception message.

Similarly

print(better_calc(5, *, 5))

This returns ''SyntaxError: invalid syntax'', without triggering the exception or the exception message.

I realize that if I included quotation marks on the operator, that the code would work, however, my goal is to trigger the exceptions.

def better_calc(num1, op, num2):
    try:
        if op == "+":
            result = num1+num2
        elif op == "-":
            result = num1-num2
        elif op == "*":
            result = num1*num2
        elif op == "/":
            num1/num2
    except NameError:
        print(f"Error: Name error. Please check your input")
    except UnboundLocalError:
        print(f"Error: Value error. Please check your input")
    except SyntaxError:
        print(f"Error: Syntax Error. Please check your input")

    print(num1, op, num2, "=")
    return result

print(better_calc(5, 5, 5))
4
  • 6
    Because the error occurs outside your function; it never gets invoked, so cannot possibly catch it. You can't catch syntax errors (outside of exec/eval) because if your code isn't syntactically valid it cannot run. Commented Jun 16, 2020 at 17:10
  • Can you please clarify what you are trying to do? Arguments are evaluated before passing them to functions – catching errors inside the function does not cover malformed argument syntax or names. Also, operators are not first class – you cannot pass the + operator to a function, for example. Use operator.add for that – though your function is written to expect the string +, not the corresponding operation. Commented Jun 16, 2020 at 17:13
  • Possible dupe: stackoverflow.com/questions/4148015/… Commented Jun 16, 2020 at 17:14
  • SyntaxErrors cannot be caught by code: they are raised during compile time, when Python parses your entire source code into bytecode prior to executing it, not during actual runtime. Commented Jun 16, 2020 at 17:16

1 Answer 1

2

Just to consolidate the answers already given in the comments, try/except blocks can only handle errors that are raised between the try: and the first except block.

try:
    # raised exceptions in this block can be caught
    foo = "bar"
except FooError:
    # catches a raised FooError but any exceptions raised here are
    # outside of the try block and will not be handled. Another try/except
    # block could be added here to catch these exceptions
    pass
except Exception as e:
    # a trick to log exceptions but then let the exception run
    print(e)
    raise

The call to the function print(better_calc(5, g, 5)) is outside of the function's try block and will not be caught.

And syntax errors like print(better_calc(5, *, 5)) keep the program from even running, which is definitely outside of the function's try block.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.