Get one quick Python tip each week Weekly Python advice: one quick Python tip every week

# How to throw an exception in Python

Share
Series: Exceptions
5 min. read 3 min. video Python 3.8—3.11
Watch as video
03:12

Let's talk about how to throw an exception in Python.

## A function that raises an exception

Here we have a program called `is_prime`:

``````from math import sqrt

def is_prime(number):
for candidate in range(2, int(sqrt(number))+1):
if number % candidate == 0:
return False
return True
``````

When we pass a negative number to the `is_prime` function, it will pass that negative number into the `math.sqrt` function, which raises a `ValueError` exception:

``````>>> is_prime(-2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/trey/is_prime.py", line 5, in is_prime
for candidate in range(2, int(sqrt(number))+1):
ValueError: math domain error
``````

The `sqrt` function in Python's `math` module raises an exception when it's given a negative number.

Note that I said "raises" an exception. In Python we usually talk about "how to raise an exception" instead of "how to throw an exception". This is partly due to the fact that `raise` is a Python keyword (as we'll see shortly) while `throw` is not.

## Sometimes exceptions are more appropriate than bad data

There are probably some cases where `is_prime` should be raising an exception but isn't right now. For example, if we pass a floating point number to the `is_prime` function, it returns an answer:

``````>>> is_prime(4.0)
False
``````

And sometimes it returns a really weird answer:

``````>>> is_prime(4.5)
True
``````

It doesn't make sense to ask a non-integer whether it's prime, so our `is_prime` function should probably raise an exception when given a floating point number.

Also, if we pass in `0` or `1` to `is_prime`, it returns `True`:

``````>>> is_prime(1)
True
``````

It should probably either return `False` or raise an exception instead (depending on how we'd prefer to implement `is_prime`).

## Raising an exception when a specific condition is met

We could modify our `is_prime` function to check for these two conditions, raising an exception if either of those conditions are met.

First we'll ask whether the given number is an instance of the `float` class, and we'll raise a `TypeError` exception if it is:

``````    if isinstance(number, float):
raise TypeError(f"Only integers are accepted: {number}")
``````

We're using Python's `raise` statement and passing in a `TypeError` exception object. We're using `TypeError` because the wrong type was given.

Also, if the number given is less than `2`, we'll say that this isn't a valid value, so we'll raise a `ValueError` exception. The message for our `ValueError` exception will declare that only integers above `1` are accepted:

``````    if number < 2:
raise ValueError(f"Only integers above 1 are accepted: {number}")
``````

Here's a updated `is_prime` function with both of those conditions and `raise` statements:

``````def is_prime(number):
if isinstance(number, float):
raise TypeError(f"Only integers are accepted: {number}")
if number < 2:
raise ValueError(f"Only integers above 1 are accepted: {number}")
for candidate in range(2, int(sqrt(number))+1):
if number % candidate == 0:
return False
return True
``````

In both of these cases, the error message we give to our exception object shows the number we were given, which will make our error message as helpful as possible when we're debugging our code.

Wow when we call the `is_prime` function with a floating point number, it raises a `TypeError` exception which says only integers are accepted:

``````>>> is_prime(4.5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/trey/is_prime2.py", line 6, in is_prime
raise TypeError(f"Only integers are accepted: {number}")
TypeError: Only integers are accepted: 4.5
``````

Similarly, if we call `is_prime` with `1` or `0`, it raises a `ValueError` exception:

``````>>> is_prime(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/trey/is_prime2.py", line 8, in is_prime
raise ValueError(f"Only integers above 1 are accepted: {number}")
ValueError: Only integers above 1 are accepted: 1
``````

In both cases, the traceback that Python prints out shows the friendly error message we gave our exception objects.

## Python has built-in exceptions

Where did `TypeError` and `ValueError` come from? We didn't define those classes, so they must be defined in Python.

If you look at help on the `builtins` module in Python, or if you look at the documentation for exceptions, you'll see the exception hierarchy:

``````>>> import builtins
>>> help(builtins)
Help on built-in module builtins:

NAME
builtins - Built-in functions, exceptions, and other objects.

DESCRIPTION
Noteworthy: None is the `nil' object; Ellipsis represents `...' in slices.

CLASSES
object
BaseException
Exception
ArithmeticError
FloatingPointError
OverflowError
ZeroDivisionError
AssertionError
AttributeError
BufferError
EOFError
ImportError
ModuleNotFoundError
LookupError
IndexError
KeyError
MemoryError
NameError
UnboundLocalError
OSError
BlockingIOError
ChildProcessError
ConnectionError
BrokenPipeError
ConnectionAbortedError
ConnectionRefusedError
ConnectionResetError
FileExistsError
FileNotFoundError
InterruptedError
PermissionError
ProcessLookupError
TimeoutError
ReferenceError
RuntimeError
NotImplementedError
RecursionError
StopAsyncIteration
StopIteration
SyntaxError
IndentationError
TabError
SystemError
TypeError
ValueError
UnicodeError
UnicodeDecodeError
UnicodeEncodeError
UnicodeTranslateError
Warning
BytesWarning
DeprecationWarning
EncodingWarning
FutureWarning
ImportWarning
PendingDeprecationWarning
ResourceWarning
RuntimeWarning
SyntaxWarning
UnicodeWarning
UserWarning
GeneratorExit
KeyboardInterrupt
SystemExit
``````

`TypeError` and `ValueError` are just two of the many built-in exceptions in Python. There are dozens of exceptions built into Python. We don't have to import anything in order to use these exceptions; they're just built-in.

We can define our own custom exception types by inheriting from another exception class, but it's a little bit unusual to do so. Unless you really need to distinguish your exceptions from exceptions that are built into Python, you probably won't create custom exceptions often.

The most common exception type I raise in my code is a `ValueError` exception.

## Use `raise` to throw an exception in Python

If you have a specific condition in your function that should loudly crash your program (if/when that condition is met) you can raise an exception (a.k.a. "throw an exception") by using the `raise` statement and providing an exception object to raise.

You can make an exception object by calling an exception class, passing in a helpful error message.

#### Series: Exceptions

Exceptions happens! When exceptions happen, how should interpret the traceback for an exception? And how, when, and where should you catch exceptions?