4.12 Output Statement
Python print() in detail: syntax, formatting, separators, streams, files, JSON, logging, and practical AWS, Kubernetes, Docker, and CI/CD output examples.
What Is print()?
print() writes values to a text stream, usually the terminal. It accepts zero or more positional values, converts them to text, separates them with sep, and appends end.
print("Hello", "World")
Output:
Hello World
print() is useful for human-readable status messages, command-line tools, quick debugging, and small scripts. For long-running production services, use the logging module so messages have levels, timestamps, and configurable destinations.
Basic Syntax
print(*objects, sep=" ", end="\n", file=None, flush=False)
| Argument | Purpose | Default |
|---|---|---|
*objects | Values to write; any number is allowed | None |
sep | Text placed between values | One space |
end | Text written after the final value | Newline (\\n) |
file | Text stream receiving the output | Standard output (sys.stdout) |
flush | Force buffered output to be written immediately | False |
All arguments after the values are keyword arguments. This is valid:
print("deployment", "complete", sep=" | ", end="!\n")
Output:
deployment | complete!
Printing Values
Print One Value
service = "orders-api"
print(service)
Print Multiple Values
Python converts each value to text for display.
service = "orders-api"
replicas = 3
healthy = True
print(service, replicas, healthy)
Output:
orders-api 3 True
This is usually clearer than manually concatenating strings, and it avoids type errors such as trying to concatenate a string and an integer.
Print No Value
Calling print() with no arguments writes one blank line.
print("Deployment summary")
print()
print("Status: healthy")
Print Collections
Lists and dictionaries are displayed using their normal Python representation.
regions = ["us-east-1", "eu-west-1"]
configuration = {"replicas": 3, "environment": "staging"}
print(regions)
print(configuration)
For machine-readable output, use JSON rather than relying on the Python representation. See Structured JSON Output.
The sep Parameter
sep controls the text inserted between multiple positional values. Its default is one space.
print("api", "staging", "healthy", sep=" | ")
Output:
api | staging | healthy
Useful separators include commas, colons, tabs, and empty text:
print("2026-09-23", "10:30:00", "INFO", sep=" ")
print("name", "status", "latency_ms", sep=",")
print("loading", end="")
print(".", end="")
print(".")
sep is ignored when there is only one object.
The end Parameter
end controls what is written after the final value. The default is a newline.
print("first")
print("second")
Output:
first
second
Set end="" to continue on the same line:
print("Checking", end=" ")
print("database", end=" ")
print("OK")
Output:
Checking database OK
It can also be used for a simple progress display:
for step in range(1, 4):
print(f"step {step}", end=" ", flush=True)
print("complete")
For a real progress bar, use a library such as tqdm rather than building terminal control behavior manually.
Escape Characters
Escape characters represent special characters inside strings. The complete reference is 4.13 Escape Characters.
print("Line 1\nLine 2")
print("Name\tStatus")
print("She said, \"healthy\"")
Output:
Line 1
Line 2
Name Status
She said, "healthy"
Use a raw string for text containing many backslashes, such as a Windows path or regular expression:
print(r"C:\\Users\\deploy\\logs")
Formatted Output with f-Strings
f-strings are the preferred way to place expressions inside output text.
service = "payments-api"
status = "healthy"
latency_ms = 42.7
print(f"{service}: {status}, latency={latency_ms:.1f} ms")
Common formatting options:
completion = 0.9375
replicas = 3
print(f"Completion: {completion:.1%}")
print(f"Replicas: {replicas:02d}")
print(f"Cost: ${12.5:,.2f}")
Output:
Completion: 93.8%
Replicas: 03
Cost: $12.50
Expressions can be placed inside braces, but keep complicated logic outside the output statement:
is_healthy = replicas > 0
print(f"Ready: {is_healthy}")
str() and repr() Output
print() uses the readable string form of values. Use repr() when debugging and you need to see quotes, escape characters, or whitespace.
value = " staging\n"
print(value)
print(repr(value))
Output:
staging
' staging\n'
This distinction is useful when diagnosing configuration values that contain unexpected spaces or newlines.
Writing Output to a File or Stream
By default, output goes to sys.stdout. The file parameter sends it to another text stream.
with open("deployment-report.txt", "w", encoding="utf-8") as report:
print("Deployment completed", file=report)
print("Environment: staging", file=report)
Use sys.stderr for errors or diagnostic messages that should be separate from normal output:
import sys
print("Deployment started")
print("Warning: replica count is low", file=sys.stderr)
This separation allows a shell or CI system to redirect normal results and errors independently.
Buffering and flush=True
Some streams buffer output before writing it. This can make a long-running script appear stuck, especially when output is sent to a pipe or CI log. flush=True requests immediate flushing.
import time
for item in ["download", "extract", "deploy"]:
print(f"Starting {item}...", flush=True)
time.sleep(1)
Use flushing for progress or heartbeat messages, not for every normal log line without a reason.
Structured JSON Output
Human-readable output is useful at a terminal, but automation works better with stable JSON keys.
import json
result = {
"service": "orders-api",
"environment": "staging",
"healthy": True,
"replicas": 3,
}
print(json.dumps(result))
Pretty-print JSON for people reviewing a report:
print(json.dumps(result, indent=2, sort_keys=True))
Do not print secrets, access tokens, passwords, or complete cloud API responses if they may contain sensitive data.
print() Versus logging
Use print() for short scripts, simple user feedback, and quick demonstrations. Use logging for production services and automation that needs levels, timestamps, handlers, or filtering.
import logging
logging.basicConfig(level=logging.INFO, format="%(levelname)s %(message)s")
logging.info("Deployment started")
logging.warning("Rollback threshold is near")
Avoid logging credentials, authorization headers, full environment variables, or sensitive customer data.
Cloud and DevOps Examples
Display an AWS Resource Summary
The SDK response is converted into a small stable summary rather than printing the entire response, which may contain unnecessary details.
import boto3
ec2 = boto3.client("ec2", region_name="us-east-1")
response = ec2.describe_instances(
Filters=[{"Name": "instance-state-name", "Values": ["running"]}]
)
running_instances = [
instance
for reservation in response["Reservations"]
for instance in reservation["Instances"]
]
print(f"Running instances: {len(running_instances)}")
for instance in running_instances:
print(instance["InstanceId"], instance.get("InstanceType"), sep=" | ")
In real automation, obtain the region and credentials from the AWS configuration or workload identity rather than hardcoding secrets in output code.
Print an AWS Deployment Result as JSON
import json
deployment = {
"application": "orders-api",
"region": "us-east-1",
"version": "2026.09.23",
"status": "success",
}
print(json.dumps(deployment))
This format can be consumed by a CI job, monitoring system, or another script.
Report Kubernetes Pod Status
import subprocess
result = subprocess.run(
["kubectl", "get", "pods", "--namespace", "staging", "--no-headers"],
capture_output=True,
text=True,
check=True,
)
for line in result.stdout.splitlines():
columns = line.split()
if len(columns) >= 3:
print(f"{columns[0]} | ready={columns[1]} | status={columns[2]}")
Using an argument list avoids shell parsing problems. Do not pass unchecked user input into shell=True.
Show Docker Image Build Progress
import subprocess
image_tag = "orders-api:2026.09.23"
print(f"Building {image_tag}...", flush=True)
subprocess.run(["docker", "build", "--tag", image_tag, "."], check=True)
print(f"Built {image_tag}")
For detailed command output, let the subprocess inherit the terminal or CI stream instead of capturing and printing it only after the command finishes.
Produce a CI/CD Check Result
import json
checks = {
"unit_tests": "passed",
"security_scan": "passed",
"image_scan": "warning",
}
failed = [name for name, status in checks.items() if status == "failed"]
summary = {"checks": checks, "failed": failed, "success": not failed}
print(json.dumps(summary))
A CI job can parse the JSON and decide whether a pipeline stage should continue. Human-facing status messages can still use f-strings.
Print a Log Scanner Summary
from collections import Counter
levels = ["INFO", "ERROR", "INFO", "WARNING", "ERROR"]
counts = Counter(levels)
for level, count in sorted(counts.items()):
print(f"{level:<8} {count:>4}")
Output:
ERROR 2
INFO 2
WARNING 1
Output Design for Automation
Choose output based on who or what consumes it:
| Consumer | Good output choice |
|---|---|
| Person at a terminal | Clear f-string messages with useful spacing |
| Shell pipeline | One stable value per line or a documented delimiter |
| CI/CD job | JSON or a clearly defined exit status and stream |
| Monitoring system | Structured logs through logging |
| Error handling | sys.stderr plus a non-zero process exit code |
| Large command output | Stream it rather than storing the entire result |
Output should be stable when another program parses it. Avoid adding decorative text to a machine-readable stream such as JSON.
Quick Interview Answer
“
print()writes values to a text stream. It accepts any number of objects and supportssepbetween objects,endafter the final object,filefor a destination such as a file orsys.stderr, andflushfor immediate output. I use f-strings for human-readable messages,json.dumps()for machine-readable results, andlogginginstead of scatteredprint()calls in production services.”
Common Mistakes
- Forgetting that
print()adds a newline by default and then getting unexpected line breaks. - Using string concatenation with numbers instead of multiple arguments or an f-string.
- Printing an entire cloud SDK response, which can produce noisy output or expose sensitive fields.
- Sending errors to standard output instead of
sys.stderr, making shell and CI redirection confusing. - Using human-readable labels in output that another program expects to parse as JSON.
- Omitting
flush=Truewhen a long-running progress or heartbeat message must appear immediately. - Using
print()as the logging system for a production service instead of configuringlogging. - Logging passwords, tokens, authorization headers, or complete environment variables.
Add More Questions to This Guide
Know a question that should be here? Share it and help the community!
Open Google Form