To exit a function in Python, use return. It stops the function on that line and hands a value back to the caller; a bare return hands back None. Code after it never runs:
def ship(order):
if not order:
return # leave early, returns None
print("shipping", order)
In this tutorial, I’ll walk through every way out of a function I actually use, all run on Python 3.12.5 in a Windows Command Prompt.
That covers guard clauses, raising errors, break versus return, nested loops, sys.exit(), finally and generators.
Exit a function early with return and guard clauses
A guard clause checks for a bad case at the top and returns right away, so the main logic doesn’t sit inside nested if blocks. For the full picture of return values, see my Python return statement guide:
def apply_discount(total, coupon):
if total <= 0:
return 0.0 # guard clause: leave right away
if coupon is None:
return total
print(f" applying {coupon}")
return round(total * 0.90, 2)
def log_order(order_id):
print(f" logged {order_id}") # no return statement at all
print(apply_discount(0, "SAVE10"))
print(apply_discount(84.50, None))
print(apply_discount(84.50, "SAVE10"))
print(log_order("A-1001"))
Output:
0.0
84.5
applying SAVE10
76.05
logged A-1001
None

log_order() gives back None.A function without any return still exits at its last line, and the caller gets None.
Exit a function by raising an exception
When the input is wrong, don’t return a fake value. Raise an exception: the function stops, and the caller decides what to do:
def charge_card(amount):
if amount <= 0:
raise ValueError(f"amount must be positive, got {amount}")
return f"charged ${amount:.2f}"
for amount in (49.99, -5):
try:
print(charge_card(amount))
except ValueError as err:
print("declined:", err)
Output:
charged $49.99
declined: amount must be positive, got -5
The -5 charge never reaches the return line. If the condition you’re leaving is an if block rather than a function, read how to exit an if statement in Python.
What’s the difference between break and return in a function?
break leaves only the innermost loop, and the function keeps going. return leaves every loop and the function at once, which makes it the clean way out of nested loops. More on loop control in Python break and continue:
orders = [("Austin", [120.00, 89.99]), ("Denver", [45.50, 310.00]), ("Boston", [12.25])]
def scan_with_break(limit):
for city, totals in orders:
for total in totals:
if total > limit:
print(f" break at {city} ${total:.2f}")
break # leaves the inner loop only
return "checked every city"
def scan_with_return(limit):
for city, totals in orders:
for total in totals:
if total > limit:
return city, total # leaves both loops and the function
return None
print(scan_with_break(100))
print(scan_with_return(100))
print(scan_with_return(500))
Output:
break at Austin $120.00
break at Denver $310.00
checked every city
('Austin', 120.0)
None

break stops once per city but the scan still finishes; return stops at the first match.Should you use sys.exit() or return inside a function?
sys.exit() doesn’t exit the function; it raises SystemExit and ends the whole program unless something catches it. That’s a separate job, covered in how to exit a Python program:
import sys
def load_config(path):
if not path.endswith(".toml"):
sys.exit(f"bad config file: {path}")
return {"path": path}
try:
load_config("settings.ini")
except SystemExit as exc:
print("caught SystemExit, code:", exc.code)
print(load_config("settings.toml"))
load_config("settings.ini")
print("this line never runs")
Output:
caught SystemExit, code: bad config file: settings.ini
{'path': 'settings.toml'}
bad config file: settings.ini

SystemExit carries the message as its code; uncaught, it prints the message and the last line never runs.In reusable functions, I return or raise and let the script’s entry point call sys.exit().
Does finally run when a function returns?
Yes. A finally block runs after return but before the caller gets the value, so cleanup always happens:
def close_register(day):
try:
print(f" counting cash for {day}")
return "closed"
finally:
print(" drawer locked") # runs after return, before the caller resumes
print(close_register("2026-10-20"))
Output:
counting cash for 2026-10-20
drawer locked
closed
Note that return only works inside a def; at module level it’s a syntax error, explained in SyntaxError: return outside function.
Use return to stop a generator function
In a generator, return ends the iteration. Any value you return isn’t yielded; it rides along on StopIteration.value:
def read_invoices(rows):
for row in rows:
if row == "END":
return f"stopped at row {rows.index(row)}" # ends the generator
yield row
print(list(read_invoices(["INV-1", "INV-2", "END", "INV-3"])))
gen = read_invoices(["INV-7", "END"])
next(gen)
try:
next(gen)
except StopIteration as stop:
print("StopIteration value:", stop.value)
Output:
['INV-1', 'INV-2']
StopIteration value: stopped at row 1

list() collects only the rows before END, and the returned text shows up on the exception.If you’re still exploring functions, these come next:
Frequently asked questions
How do I exit a function in Python?
Use return, with or without a value. Execution goes back to the caller immediately.
What does a function return if it exits without a value?
None, whether you write a bare return or just reach the last line.
Can break exit a function?
No. break only leaves the current loop. Use return to leave the function.
How do I exit nested loops inside a function?
Put the loops in a function and return from the inner loop.
Is sys.exit() the same as return?
No. sys.exit() raises SystemExit and stops the program unless it’s caught.
Where is the return statement documented?
See the return statement in the Python docs.

Bijay Kumar is a 13-time Microsoft MVP with more than 18 years in software development, and the founder of Python Guides and TSinfo Technologies. He started out building .NET and SharePoint solutions at HP, TCS and KPIT before moving into Python, machine learning and AI, and he also builds web apps with TypeScript and React. He writes the tutorials here himself, and every example is run before publishing so you see the real output. More about Bijay · Microsoft MVP profile · LinkedIn