Python online course

Nested Exception Handling Statements in Python

Learn nested try/except statements and while-loop validation patterns for safely retrying numeric input in Python.

When a Python program asks for input, the user may enter something different from what the program expects. Exception handling lets the program respond to that problem instead of stopping with a traceback. This lesson explains nested exception handling, repeated input with a while loop, and safe retry decisions.

Prerequisites and key terms

You should understand variables, assignment, str, int, bool, input(), print(), if statements, while loops, and Python indentation. See getting user input and while loops if these ideas are new.

  • Exception: an event raised during execution that interrupts normal flow unless it is handled.
  • Try block: the block containing code that may raise an exception.
  • Except clause: the block that runs when a matching exception is raised by its associated try block.
  • Type conversion: changing a value from one type to another, such as converting input text to an integer.
  • Boolean flag: a True or False variable used to control a loop.
  • Sentinel value: a particular value that signals a control-flow decision. In this lesson, 0 means retry.

Why use nested exception handling?

Nesting means placing one control structure or exception-handling workflow inside another structure's scope. A genuinely nested exception handler has a try/except block inside another try or except block. This can be useful when the original operation fails and the recovery action can also fail.

For example, converting an age may fail. After that failure, the program can ask whether the user wants to retry. Converting the retry response to an integer is a second operation that can also fail, so it needs its own protection.

try:
    age = int(input("Enter your age: "))
except ValueError:
    print("Please enter a whole number.")
    try:
        retry_choice = int(input("Enter 0 to try again or another number to exit: "))
    except ValueError:
        print("The retry choice was not a number. Exiting.")

The inner try is genuinely nested because it is indented inside the outer except block. By contrast, two try/except blocks that appear one after another inside the same loop are sequential, not nested. Both arrangements can be useful; the structure should match the relationship between the operations.

Converting input text to an integer

input() always returns text, represented by the str type. Even if the user types 42, the result is the string "42". The int() function performs a type conversion:

age_text = input("Enter your age: ")
age = int(age_text)

If the text does not represent a valid integer, int() raises ValueError. A specific except ValueError clause can handle that expected conversion failure.

try:
    age = int(input("Enter your age: "))
    print(f"Your age is {age}.")
except ValueError:
    print("Please enter your age as a whole number, such as 25.")

Without the handler, input such as "twenty" normally terminates this small program with a traceback. With the handler, the program displays a correction message and can choose what to do next.

Retrying with a Boolean flag

A while loop continues while its condition is true. A Boolean flag makes the relationship between the loop and its exit condition explicit. A failed conversion leaves the flag true so the user can retry; a successful conversion or an exit decision changes the flag to false.

should_retry = True

while should_retry:
    try:
        age = int(input("Enter your age: "))
        print(f"Accepted age: {age}")
        should_retry = False
    except ValueError:
        print("Please enter a whole number.")
        should_retry = False

Here, the loop asks once. A valid age sets should_retry to False. An invalid age also ends the loop because this version has no retry question yet. The next example adds that decision.

Retry-or-exit after an invalid age

This example uses 0 as a sentinel value: entering 0 at the retry prompt starts another age attempt, while any other numeric value exits. The retry conversion has a separate try block because it can raise its own ValueError.

should_retry = True

while should_retry:
    try:
        age = int(input("Enter your age: "))
        print(f"Accepted age: {age}")
        should_retry = False
    except ValueError:
        print("Please enter your age as a whole number.")

        try:
            retry_choice = int(
                input("Enter 0 to try again or another number to exit: ")
            )
        except ValueError:
            print("The retry choice must be a number. Exiting.")
            should_retry = False
        else:
            if retry_choice == 0:
                should_retry = True
            else:
                should_retry = False

print("Input process finished.")

The inner handler treats a nonnumeric retry response as an exit decision. Another valid design could ask for the retry choice again, but that would require another loop or a separate validation function.

How the control flow works

  1. The outer while loop checks should_retry.
  2. The age conversion runs inside the outer try block.
  3. If conversion succeeds, the age is usable and should_retry becomes False.
  4. If conversion raises ValueError, the outer except message explains the expected input.
  5. The nested try validates the restart response.
  6. A retry value of 0 leaves the flag true, so the next loop iteration asks for an age again.
  7. A nonzero number or invalid retry response sets the flag false, so the loop ends.

Code after an except block continues normally unless the program explicitly changes flow. Common ways to change flow include assigning a loop flag, using break, using continue, returning from a function, or allowing another exception to propagate.

Tracing common input cases

Age inputConversion resultException handler actionRestart inputLoop outcome
21Conversion succeedsPrint the accepted age and set the flag to FalseNot requestedEnds normally
abcValueErrorDisplay the whole-number message0Flag stays true; ask for an age again
abcValueErrorDisplay the whole-number message1Flag becomes false; exit the loop
abcValueErrorDisplay the whole-number messageagainInner ValueError handler reports the problem and exits safely

Cleaner pattern: retry until conversion succeeds

If the only goal is to keep asking until a valid integer is entered, nested handling is unnecessary. Put one protected conversion inside a loop, use continue after invalid input, and use break after success.

while True:
    try:
        age = int(input("Enter your age: "))
    except ValueError:
        print("Please enter a whole number, such as 25.")
        continue
    else:
        break

print(f"Using age {age}.")

continue skips the rest of the current iteration and starts the next one. break immediately exits the nearest loop. A function could use return age instead, which separates input validation from the rest of the program. These approaches often read more clearly than repeatedly assigning a Boolean flag.

Use nested handling when recovery has its own operation that can fail, such as validating a retry choice, or when the recovery workflow needs separate treatment. Use the simpler loop when every failure has the same response: display an error and ask again.

Choosing an exception clause

PatternWhat it catchesAppropriate useRisk or limitation
except ValueError:Conversion and other operations that raise ValueErrorExpected invalid integer inputDoes not catch unrelated exception types
except Exception:Most ordinary application exceptionsA carefully designed top-level boundary when several errors need common handlingCan hide the exact cause and make debugging harder
except:Nearly all exceptions, including interruptsRare, specialized cleanup or boundary casesCan hide programming errors and keyboard interrupts; generally avoid it

Prefer except ValueError for int() conversion. A bare except can catch unrelated problems, including programming errors and a keyboard interrupt from the user. Catching only the expected exception keeps failures visible and makes the program easier to maintain.

Exception-handling design practices

  • Keep the try block limited to the statement expected to fail. For example, protect int(input(...)) rather than a large section of unrelated code.
  • Use descriptive names such as retry, should_retry, age, and retry_choice.
  • Make messages specific: say that a whole number is expected rather than displaying a vague error.
  • Make every loop exit path visible. Set the Boolean flag to False, use break, or return from a function when the process should stop.
  • Keep retry logic in the invalid-input path if valid input should proceed immediately. Do not place the retry prompt after the whole loop unless that is intentionally the workflow.

Troubleshooting

The program stops when letters are entered for an age

The int() conversion is not protected by except ValueError. Put the conversion in a try block and decide whether the handler should retry or exit.

The retry prompt crashes on text

The retry response is also passed to int(), so it has a second ValueError risk. Protect that conversion separately, as in the nested example, and choose a safe behavior for invalid retry input.

The loop never ends

The loop flag may never be changed, or the successful path may not use break. Check every path through the loop and confirm that an intended exit assigns False or executes break.

A valid age still leads to a retry prompt

The retry prompt may be outside the error-only path. Move it into the age conversion's except block if retry should be offered only after invalid input.

Unexpected errors disappear

A bare except may be catching more than the expected conversion error. Replace it with except ValueError when integer conversion is the operation being validated.

Running the examples

Save an example in a file ending in .py, or run it in a Python interpreter. No external packages or configuration are required. For execution options, see how to run Python code. Related syntax is covered in try and except statements, catching specific exceptions, the break statement, and the continue statement.

Summary

  • input() returns text, and int() converts valid numeric text to an integer.
  • Invalid integer text raises ValueError.
  • A while loop can repeat input until conversion succeeds or the user chooses to exit.
  • A nested try/except is useful when the recovery action, such as validating a retry choice, can also fail.
  • Use except ValueError instead of a bare except for expected conversion failures.
  • break, continue, and function return can replace some Boolean-flag workflows.