Syntax errors (parsing errors) occur when Python can’t understand your code:
>>> while True print('Hello world') File "<stdin>", line 1 while True print('Hello world') ^^^^^SyntaxError: invalid syntax
The parser shows the offending line and points to the error location with arrows. In this case, the error is at print() because a colon (:) is missing.
>>> while True:... try:... x = int(input("Please enter a number: "))... break... except ValueError:... print("Oops! That was no valid number. Try again...")
How it works:
The try clause is executed
If no exception occurs, the except clause is skipped
If an exception occurs, the rest of the try clause is skipped
If the exception matches the type in except, that clause is executed
If the exception doesn’t match, it’s passed to outer try statements
When handling an exception, you can raise another exception and preserve the context:
>>> try:... open("database.sqlite")... except OSError:... raise RuntimeError("unable to handle error")...Traceback (most recent call last): File "<stdin>", line 2, in <module> open("database.sqlite")FileNotFoundError: [Errno 2] No such file or directory: 'database.sqlite'During handling of the above exception, another exception occurred:Traceback (most recent call last): File "<stdin>", line 4, in <module> raise RuntimeError("unable to handle error")RuntimeError: unable to handle error
Explicit chaining:
>>> def func():... raise ConnectionError...>>> try:... func()... except ConnectionError as exc:... raise RuntimeError('Failed to open database') from exc...Traceback (most recent call last): File "<stdin>", line 2, in <module> func()ConnectionErrorThe above exception was the direct cause of the following exception:Traceback (most recent call last): File "<stdin>", line 4, in <module> raise RuntimeError('Failed to open database') from excRuntimeError: Failed to open database
Disable chaining:
>>> try:... open('database.sqlite')... except OSError:... raise RuntimeError from None...Traceback (most recent call last): File "<stdin>", line 4, in <module> raise RuntimeError from NoneRuntimeError
Create custom exceptions by deriving from Exception:
class InputError(Exception): """Exception raised for errors in the input. Attributes: expression -- input expression in which the error occurred message -- explanation of the error """ def __init__(self, expression, message): self.expression = expression self.message = message
Most exceptions are named with names ending in “Error”, similar to standard exceptions.
Use except* to handle specific exception types in a group:
>>> try:... f()... except* OSError as e:... print("There were OSErrors")... except* SystemError as e:... print("There were SystemErrors")...There were OSErrorsThere were SystemErrors
>>> try:... raise TypeError('bad type')... except Exception as e:... e.add_note('Add some information')... e.add_note('Add some more information')... raise...Traceback (most recent call last): File "<stdin>", line 2, in <module> raise TypeError('bad type')TypeError: bad typeAdd some informationAdd some more information
Practical example:
>>> def f():... raise OSError('operation failed')...>>> excs = []>>> for i in range(3):... try:... f()... except Exception as e:... e.add_note(f'Happened in Iteration {i+1}')... excs.append(e)...>>> raise ExceptionGroup('We have some problems', excs)