Errors and Exceptions in Python


When you’re learning Python, you’re bound to run into errors. These come in two main types: syntax errors and exceptions.

Syntax Errors

Syntax errors, or parsing errors, happen when Python can’t understand your code. For example:

while True print('Hello world')

You’ll see something like this:

  File "<stdin>", line 1
    while True print('Hello world')
               ^^^^^
SyntaxError: invalid syntax

Here, Python highlights the spot where it got confused. It’s not always the actual mistake, but it helps narrow things down. In this case, the issue is a missing colon (:) after while True.

Exceptions

Even if your code is syntactically correct, it might still crash when something goes wrong during execution. These runtime errors are called exceptions.

Examples:

10 * (1 / 0)
# ZeroDivisionError: division by zero

4 + spam * 3
# NameError: name 'spam' is not defined

'2' + 2
# TypeError: can only concatenate str (not "int") to str

Each exception type describes what went wrong: dividing by zero, using an undefined name, or trying to mix strings and integers.

Handling Exceptions

You can write code to catch and handle exceptions gracefully using try and except. Here’s a basic example:

while True:
    try:
        number = int(input("Enter a number: "))
        break
    except ValueError:
        print("Oops! That wasn't a valid number. Try again...")

How this works:

  • The code inside try runs.
  • If it runs fine, except is skipped.
  • If an error occurs, Python jumps to the matching except block.
  • If no matching except is found, the program crashes.

You can have multiple except blocks:

try:
    # some risky code
except FileNotFoundError:
    print("File not found!")
except ValueError:
    print("Invalid value!")
except Exception as e:
    print(f"Unexpected error: {e}")
    raise

You can also catch multiple exceptions in a single block:

try:
    # code
except (TypeError, NameError):
    print("A type or name error occurred.")

Custom Exception Classes

You can define your own exception classes:

class MyError(Exception):
    pass

raise MyError("Something went wrong!")

Exceptions can carry extra data, too:

try:
    raise Exception("spam", "eggs")
except Exception as e:
    print(type(e))     # <class 'Exception'>
    print(e.args)      # ('spam', 'eggs')
    print(e)           # ('spam', 'eggs')
    x, y = e.args
    print("x =", x)
    print("y =", y)

Using else with try/except

You can run code if no exception occurs using else:

for arg in sys.argv[1:]:
    try:
        f = open(arg, 'r')
    except OSError:
        print("Cannot open file:", arg)
    else:
        print(arg, "has", len(f.readlines()), "lines")
        f.close()

finally: Cleanup No Matter What

The finally block is used for cleanup actions that must happen no matter what:

try:
    raise KeyboardInterrupt
finally:
    print("Goodbye, world!")

Even if an error happens or the user interrupts, the finally block runs.

More realistic example:

def divide(x, y):
    try:
        result = x / y
    except ZeroDivisionError:
        print("division by zero!")
    else:
        print("result is", result)
    finally:
        print("executing finally clause")

This will always print the finally message, whether an error occurs or not.

Using with for Automatic Cleanup

Instead of manually opening and closing files:

with open("myfile.txt") as f:
    for line in f:
        print(line, end="")

This way, the file is automatically closed, even if an error happens.

Raising Exceptions

You can raise exceptions yourself:

raise ValueError("Invalid input!")

To re-raise an exception after catching it:

try:
    raise NameError("HiThere")
except NameError:
    print("An exception flew by!")
    raise

Exception Chaining

If one error leads to another, you can chain them:

try:
    open("missing_file.txt")
except OSError as e:
    raise RuntimeError("Unable to handle error") from e

To suppress the original exception info:

try:
    open("missing_file.txt")
except OSError:
    raise RuntimeError from None

Multiple Unrelated Exceptions (Python 3.11+)

If you want to raise multiple unrelated exceptions at once:

def f():
    excs = [OSError("error 1"), SystemError("error 2")]
    raise ExceptionGroup("Multiple errors occurred", excs)

You can handle specific ones using except*:

try:
    f()
except* OSError:
    print("There were OSErrors")
except* SystemError:
    print("There were SystemErrors")

This is useful for async code, tests, or batch processing where multiple things can fail independently.


  • Related Posts

    Interactive Mode

    There are two variants of the interactive REPL in Python. The classic basic interpreter is supported on all platforms with minimal line control capabilities. On Windows, or Unix-like systems with…

    Read more

    Interactive Input Editing and History Substitution

    Some versions of the Python interpreter support editing of the current input line and history substitution, similar to facilities found in the Korn shell and the GNU Bash shell. This…

    Read more

    You Missed

    2,800-year-old royal tomb discovered in Turkey

    2,800-year-old royal tomb discovered in Turkey

    Bacteria in the mouth linked to dangerous neurological disease

    Bacteria in the mouth linked to dangerous neurological disease

    The Universe’s Most Powerful Explosions Have Been Found

    The Universe’s Most Powerful Explosions Have Been Found

    Elon Musk Announces Launch of X Chat to Rival WhatsApp

    Elon Musk Announces Launch of X Chat to Rival WhatsApp

    Since When Have Bed Bugs Been With Humans? Scientists Have Found Out

    Since When Have Bed Bugs Been With Humans? Scientists Have Found Out

    Explosions on the Sun are intensifying; experts issue a warning!

    Explosions on the Sun are intensifying; experts issue a warning!