raise
Until now, the boxes in our column cracked on their own: Python raised the exception when a division or int failed. Now a function will signal the break itself.
Picture a bank cashier. You ask to withdraw more than the account holds. The cashier does not silently hand you an empty envelope—you might not open it and walk away. The cashier refuses out loud, so the refusal cannot go unnoticed.
A function, too, cannot always do what it is asked to do. Returning a special value such as None in that case is unreliable—the calling code may not check it. The raise statement raises an exception, and the function reports the error the same way built-in ones do:
def withdraw(balance, amount):
if amount > balance:
raise ValueError("not enough money")
return balance - amount
print(withdraw(100, 30)) # 70
try:
print(withdraw(100, 500))
except ValueError as e:
print("error:", e) # error: not enough moneyLet's go step by step:
withdraw(100, 30)passes the check and returns70.withdraw(100, 500)sees that500is greater than100and runsraise.- The function ends at once, and the exception goes to the
tryaround the call. - The
except ValueErrorbranch printserror: not enough money.
What goes after raise
After raise comes an exception. Only an instance of BaseException or of its descendant, or such a class itself, can be raised. There are two ways.
An object with a message
Most often you write a class with a message in parentheses: raise ValueError("not enough money"). Python creates the exception object, and the message later shows up in print(e) and in the last line of the traceback.
A class without parentheses
You can also write the class alone, raise ValueError. Then Python creates the object itself, with no message. This is rare: without a message, it is harder to see what went wrong.
The class is chosen by the meaning of the error:
ValueErrorfor an unsuitable value;TypeErrorfor an unsuitable type.
The path of an exception
raise ends the function at once, like return, but an exception goes up instead of a value. It reaches the caller, then the caller's caller, and so on, until it meets a try with a fitting except. This is the same path up the column of boxes that Python's own exceptions take.
If there is no such try all the way to the top, the program stops with a traceback. Its last call points at the line with raise, and its last line repeats the class and the message. In the first example, withdraw(100, 500) returned no value, so the outer print never ran.
Here the cashier picture ends: a cashier refuses only the person standing in front of them. An exception goes higher, until someone on its path catches it.
Raising again
Sometimes an error needs to be noticed but not fully handled: print where it happened and pass it on. For this, write raise with no arguments inside except. This is a re-raise: the same exception goes up unchanged.
def parse(text):
try:
return int(text)
except ValueError:
print("cannot read", text) # cannot read x
raise
try:
parse("x")
except ValueError:
print("caller caught it") # caller caught itLet's go step by step:
int("x")in theparsefunction raises aValueError.- The
exceptbranch inparseprintscannot read x. raisewith no arguments raises the sameValueErroragain, andparseends.- The
tryaround the call catches the exception, and the program printscaller caught it.
Without the outer try, the program would stop with a traceback pointing at int(text). A re-raise keeps the original place of the error, which matters when you look for the cause.
Common mistake
A string is written after raise instead of an exception:
def withdraw(balance, amount):
if amount > balance:
raise "not enough money" # ✗
return balance - amount
withdraw(100, 500)TypeError: exceptions must derive from BaseExceptionA string is not an exception: str is not a descendant of BaseException, so Python raises a TypeError instead. The message goes in the class's parentheses: raise ValueError("not enough money").
Key points
raiseraises an exception and ends the function at once; an exception goes up instead of a value.- After
raisecomes an exception instance or class, usually with a message:raise ValueError("not enough money"). raisewith no arguments insideexceptpasses the same exception on unchanged.- A string after
raisegives aTypeError: only a descendant ofBaseExceptioncan be raised.
Subscribe to take the course
The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.