# Functions Try Except

Hi. I am a bit confused on why the below code will produce a result of 3?
Thank you.

``````m = 0
def foo(n):
global m
assert m==0
try:
return 1/n
except ArithmeticError:
m+=1
raise

try:
foo(0)
except ArithmeticError:
m+=2
except:
m+=1
print(m)
``````

Hello,

Because youâ€™re dividing by zero, it raises exceptions along its executable path.

Adding printing statements to your test scripts really helps in understanding what is going on with your
code. Note that IDLE also has a debug tool that allows you to step through the code and monitor variables.

``````m = 0

def foo(n):

global m
assert m == 0

try:
return 1/n # Divide by zero raises an exception

except ArithmeticError:
print('entered exception 0')
m += 1 # Was '0', now is '1' after incrementing
raise   # Manually raising an exception here, causes it to go into the other exception outside
# If you comment it out, it will not go into the other exception

try:
foo(0)
except ArithmeticError: # Entered here due to the 'raise' inside the function call
print('entered exception 1')
m += 2  # Was '1', now is '3' after incrementing by 2
except:   # This exception is skipped because already caught by the previous exception due to arithmetic error of dividing by '0'
print('entered exception 2')
m += 1
print(m)
``````

You can remove the try/except in the function if you already have it outside
if youâ€™d like.

1 Like

Overall, your explanation is largely correct, with a few additional points of clarification:

Itâ€™s important to point out here that while perhaps necessary for illustrating whatever point is being made by this presumably demonstration code, (non-constant) global variables should almost always be avoided unless absolutely necessary (which they rarely ever are, at least with properly-designed code), especially by beginners, since they make errors much easier to make and harder to find and solve, and the logic much harder to follow and reason about, as is indeed the case here. `m` gets modified several different places in several different scopes, making it substantially harder to determine why it has the particular value it does at a given point in your programâ€™s execution.

Just to clarify, a bare `raise` inside an `except` block re-raises the existing exception, rather than raising a new exception as the comment might be read to implyâ€”this is the same exception, not an â€śother exceptionâ€ť.

Also, its important to note that both the OP and the explanation seem to be confusing an exception, the thing that is raised, with the `except` blocks (called `catch` blocks in many other languages) that handle them, which are of course very different things. In fact, this re-raised exception is then caught by the outer `except` block that wraps the call to `foo()`.

Again, to clarify, this `except` block is skipped (at least under normal circumstances) in the above because the `ArithmeticError` exception raised by the code is caught by the previous `except` block.

Itâ€™s also important to note that a bare `except` block is almost never what you want, as that will catch not only `Exception` subclasses but also other `BaseException` subclasses that you usually donâ€™t want to catch, like `KeyboardInterrupt` and `SystemExit`, that are intended to exit your programâ€”so if you had a bare `except` inside a main `while` loop, for instance, it could easily become to exit your program by normal means, e.g. Ctrl-C or `sys.exit()` and it could hang forever until the process was manually hard-killed. Instead, you almost always want at least `except Exception` instead, unless you know exactly what youâ€™re doing.

1 Like

Thank you for the thorough explanations!

Thank you for the clarifications and pointers!