To create a void function in Python, write a normal def function and don’t return a value. Python has no void keyword, so a function that ends without return hands back None automatically. Add -> None to make that intent clear:
def log_message(message: str) -> None:
print(f"[LOG] {message}")
I ran each script below with Python 3.12.5 in a Windows Command Prompt, and the output blocks are copied from those runs.
In this tutorial, we’ll create void functions, see why a call sometimes prints None, add type hints a checker can enforce, build a logging function, and decide when return None is worth writing.
How to create a void function in Python
A void function does a job, like printing, saving or logging, instead of computing a result. If def syntax is new to you, read how to define a function in Python first. Here I store the call’s result to show what comes back:
def print_report_header():
print("=" * 32)
print("DAILY SALES REPORT - TEXAS")
print("=" * 32)
result = print_report_header()
print(result)
print(result is None, type(result).__name__)
Output:
================================
DAILY SALES REPORT - TEXAS
================================
None
True NoneType

None of type NoneType.None is Python’s single “no value” object. That’s why result is None is the right check, not == None or a string comparison.
How to run the void function examples yourself
You only need Python from python.org with the “Add python.exe to PATH” box checked. Then:
- Paste the first example into Notepad or VS Code.
- Save it as
report_header.pyin a folder likeC:\pyguides. - Open the Command Prompt (Win + R, type
cmd, press Enter). - Run
cd C:\pyguidesand thenpython report_header.py.
Why does my Python function print None?
This is the most common void function surprise. The function prints its own line, then the outer print() shows what came back, which is None. A function that uses return in Python gives you a value you can keep using:
def show_total(order_total):
print(f"Order total: ${order_total:.2f}") # displays, returns nothing
def get_total(prices):
return round(sum(prices), 2) # hands the value back
print(show_total(84.50)) # the call prints, then print() shows None
total = get_total([19.99, 42.50, 22.01])
print(f"With tax: ${total * 1.0825:.2f}")
try:
shown = show_total(84.50)
print(shown + 5.00)
except TypeError as err:
print("TypeError:", err)
Output:
Order total: $84.50
None
With tax: $91.47
Order total: $84.50
TypeError: unsupported operand type(s) for +: 'NoneType' and 'float'

None; the returned total feeds the tax math; adding to None raises TypeError.My rule: if any later line needs the number, return it. Print only in the outer code that talks to the person running the script.
Add a -> None type hint to a Python void function
A type hint is an optional label for what a function takes and returns. Python ignores hints at run time, but a checker such as mypy reads them. Here mypy catches code that uses a void function’s result:
from typing import NoReturn
def log_import(file_name: str, row_count: int) -> None:
print(f"Imported {row_count} rows from {file_name}")
def stop_import(reason: str) -> NoReturn:
raise SystemExit(f"Import stopped: {reason}")
rows = log_import("orders_ohio.csv", 1284)
print(rows + 1)
Output:
hints.py:9: error: "log_import" does not return a value (it only ever returns None) [func-returns-value]
hints.py:10: error: Unsupported operand types for + ("None" and "int") [operator]
Found 2 errors in 1 file (checked 1 source file)

-> None function and adding to it, before the script ever runs.Don’t confuse None with NoReturn. -> None means the function finishes and returns nothing useful. NoReturn means it never finishes normally, because it always raises or exits.
Build a practical void function that writes a log file
Logging is a natural void job, since nothing needs to come back. This version catches OSError, the error family for file problems such as a missing folder. To create the file first, see how to create a file if it does not exist:
from datetime import datetime
from pathlib import Path
def write_log(message: str, log_path: str = "report_processing.log") -> None:
stamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
try:
with open(log_path, "a", encoding="utf-8") as log_file:
log_file.write(f"{stamp} - {message}\n")
except OSError as error:
print(f"Could not write to the log file: {error}")
def process_report(file_name: str) -> None:
write_log(f"Started {file_name}")
print(f"Reading {file_name}...")
write_log(f"Finished {file_name}")
Path("report_processing.log").unlink(missing_ok=True) # start the demo with an empty log
process_report("sales_california.csv")
print(Path("report_processing.log").read_text(encoding="utf-8"), end="")
write_log("This line has nowhere to go", "missing_folder/report.log")
Output:
Reading sales_california.csv...
2026-10-20 12:54:30 - Started sales_california.csv
2026-10-20 12:54:30 - Finished sales_california.csv
Could not write to the log file: [Errno 2] No such file or directory: 'missing_folder/report.log'

Both functions return None, so process_report() gets the -> None hint too. If a log step can fail in several ways, you can catch multiple exceptions in Python.
Void function vs return function in Python
Use a void function for an action and a return function when other code needs the result. If a function needs to give back several results, return multiple values from a function as a tuple.
I’ve seen plenty of scripts where one function did both, and it’s always harder to test.
| Void function | Return function | |
|---|---|---|
| Job | Print, save, log, send | Calculate or look up a value |
| Returns | None | The value you return |
| Type hint | -> None | -> float, -> str, … |
| Example | write_log(msg) | get_total(prices) |
Should you write return None in a Python void function?
Usually not. Falling off the end, a bare return and return None all give the same result. A bare return earns its place when you need to leave early:
def falls_off_end():
print("done")
def bare_return():
print("done")
return
def send_invoice(is_ready: bool) -> None:
if not is_ready:
print("Invoice INV-2026-0142 is not ready.")
return # leave early, still returns None
print("Sending invoice INV-2026-0142 for $1,250.00")
print(falls_off_end(), bare_return())
send_invoice(False)
send_invoice(True)
print(print("print is void too"))
Output:
done
done
None None
Invoice INV-2026-0142 is not ready.
Sending invoice INV-2026-0142 for $1,250.00
print is void too
None
Even print() itself is void, which is why the last line prints None. For more ways to stop early, see how to exit a function in Python. A body that holds only the pass statement returns None as well.
Four more function guides sit close to this topic:
- Call a function within a function in Python
- Use lambda functions in Python
- Fix SyntaxError: return outside function
- Functions vs methods in Python
Frequently asked questions
Does Python have a void function?
Not by keyword. Any function that finishes without returning a value acts as one and returns None.
How do I make a function return nothing in Python?
Leave out return, or use a bare return. Add -> None so readers and checkers know.
Why does my function print None?
You printed the call of a function that already prints. Return the value instead, or call it without print().
Is -> None the same as NoReturn?
No. -> None finishes and returns nothing useful. NoReturn is for functions that always raise or exit.
Can a void function take arguments in Python?
Yes. It can take any parameters, use them for its action, and still return None.
What is None in Python?
It’s the single object of type NoneType that means “no value”. See None 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