The print() built-in function outputs objects to a text stream, converting them to strings using custom separators and line terminators.
Streams, Formatting & Buffers: While simple scripts use print() for basic console display, production systems leverage its file argument for stream redirection (e.g. logging to sys.stderr or files) and flush=True for unbuffered real-time terminal progress updates. To read user input from the console, see input(). For advanced template interpolation, see format(), or convert objects to readable strings with str() and repr().
The print() function takes variable positional objects and four optional keyword arguments:
# Formal syntax of built-in print()
print(*objects, sep=' ', end='\n', file=None, flush=False)
| Parameter | Type | Default | Description & Operational Rule |
|---|---|---|---|
*objects |
Any (varargs) |
None | Zero or more objects to print, each converted to text via str(). |
sep |
str or None |
' ' (space) |
String inserted between adjacent objects. None defaults to single space. |
end |
str or None |
'\n' (newline) |
String appended after the last object. Setting end='' suppresses the newline. |
file |
File-like stream | sys.stdout |
Target output stream object implementing a write(string) method. |
flush |
bool |
False |
If True, forcibly flushes the underlying stream buffer immediately. |
| Return | None |
N/A | Always returns None. |
Customizing sep and end provides fine-grained control over console layout:
# 1. Basic invocations and parameter configurations
# Multiple items with custom separator
print("2026", "10", "15", sep="-")
# Custom end parameter to prevent default newline
print("Counting: ", end="")
for i in range(1, 4):
print(i, end="...")
print("Done!")Terminal Output:
2026-10-15
Counting: 1...2...3...Done!
Unpacking sequences into print() allows formatting list elements without joining strings manually:
# 2. Printing collections and iterable unpacking
tags = ["python", "tutorial", "builtins", "plus2net"]
# Printing list container vs. unpacked elements
print("Container format: ", tags)
print("Unpacked elements:", *tags, sep=" | ")Terminal Output:
Container format: ['python', 'tutorial', 'builtins', 'plus2net']
Unpacked elements: python | tutorial | builtins | plus2net
The file argument routes output to files, error streams, or in-memory text buffers:
# 3. Directing output to files and error streams
import sys
import io
# Directing output to sys.stderr
print("Warning: Connection timeout!", file=sys.stderr)
# Capturing print output in an in-memory string buffer
buffer = io.StringIO()
print("Captured record ID: 1045", file=buffer)
captured_output = buffer.getvalue().strip()
print("In-memory buffer captured:", captured_output)Terminal Output:
Warning: Connection timeout!
In-memory buffer captured: Captured record ID: 1045
By default, standard output buffers characters to optimize I/O performance. Setting flush=True forces the operating system to render characters to the screen immediately:
# 4. Immediate buffer flushing with flush=True
import time
# Unbuffered real-time countdown simulation
print("Initiating sequence: ", end="", flush=True)
for count in [3, 2, 1]:
print(f"{count}.. ", end="", flush=True)
print("Launch!")Terminal Output:
Initiating sequence: 3.. 2.. 1.. Launch!
Creating an animated in-place terminal progress bar using carriage returns (\r) and flush=True:
# 5. Production Recipe: Dynamic In-Place Terminal Progress Bar
def show_progress(iteration, total, bar_length=20):
"""Displays an in-place dynamic progress bar using carriage return (\r)."""
fraction = iteration / total
filled = int(fraction * bar_length)
bar = "=" * filled + "-" * (bar_length - filled)
percent = int(fraction * 100)
print(f"\rProgress: [{bar}] {percent}% Complete", end="", flush=True)
# Simulating a multi-step job
for step in range(1, 6):
show_progress(step, 5)
print(" -> Finished processing!")Terminal Output:
Progress: [====================] 100% Complete -> Finished processing!Building a dual-destination logger that writes to console and memory simultaneously:
# 6. Production Recipe: Dual-Destination Logger
class DualLogger:
def __init__(self, memory_stream):
self.stream = memory_stream
def log(self, message: str, level: str = "INFO"):
formatted = f"[{level}] {message}"
# Print to standard stdout
print(formatted)
# Simultaneously log to buffer
print(formatted, file=self.stream)
mem_log = io.StringIO()
logger = DualLogger(mem_log)
logger.log("Application started")
logger.log("Configuration loaded", level="DEBUG")Terminal Output:
[INFO] Application started
[DEBUG] Configuration loaded
Avoid string concatenation errors when mixing numbers and strings:
# 7. Common traps: string concatenation vs. multi-argument printing
# Trap 1: TypeError concatenating non-strings with +
try:
print("User ID: " + 101) # Raises TypeError
except TypeError as err:
print("Concatenation error:", err)
# Correct approaches: comma separation or f-strings
print("Correct comma: ", "User ID:", 101)
print(f"Correct f-string: User ID: {101}")Terminal Output:
Concatenation error: can only concatenate str (not "int") to str
Correct comma: User ID: 101
Correct f-string: User ID: 101
Practice stream redirection, in-place progress bars, and buffer management in our interactive companion Jupyter Notebook:
Explore interactive code cells, test custom separators, benchmark unbuffered terminal timers, and run self-validating assertions.
View on GitHub Run in Google ColabRun these unit checks directly in Python or your local environment to verify print() mechanics:
# 8. Self-verifying unit test suite for print()
import io
# Test 1: Capture standard output to StringIO
buf = io.StringIO()
print("plus2net", 2026, sep="-", end="!", file=buf)
assert buf.getvalue() == "plus2net-2026!"
# Test 2: Unpacking list to print
buf2 = io.StringIO()
items = ["A", "B", "C"]
print(*items, sep=",", file=buf2)
assert buf2.getvalue().strip() == "A,B,C"
# Test 3: Multiple objects with custom end
buf3 = io.StringIO()
for i in range(3):
print(i, end="", file=buf3)
assert buf3.getvalue() == "012"
# Test 4: print() always returns None
result = print("test", file=io.StringIO())
assert result is None
print("All print() unit assertions successfully verified!")Terminal Output:
All print() unit assertions successfully verified!
print() always returns None. Assigning its result to a variable stores None.
Set the end parameter to an empty string: print("Text", end="").
Use flush=True when printing real-time status updates (like progress bars or countdowns) without waiting for buffer flushes.
Open the file in write mode and pass the file handle: print("Hello", file=file_handle).
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.