Skip to content
elephantoo

Input & output

Lesson 5 of 38 12 min read

print() options, reading and validating input(), stdout vs stderr, sys.argv, argparse and exit codes.


A program that can't talk to the outside world isn't much use. In this lesson you'll learn the three basic channels a script uses: printing output, reading what the user types, and accepting command-line arguments. Along the way you'll meet standard error and exit codes, which matter as soon as your scripts are used by other people or other programs.

You've used print already. It has a few keyword arguments worth knowing:

Python
print("Hello", "world")                 # values separated by a space
print("Hello", "world", sep=", ")       # custom separator
print("no newline...", end=" ")         # custom line ending
print("continued")
print()                                  # blank line
print("2026", "09", "30", sep="-")
Output
Hello world
Hello, world
no newline... continued

2026-09-30

print converts every argument with str(), so you can pass numbers, lists or None directly. For anything more complex than a couple of values, reach for an f-string.

Printing a whole list one item per line is a neat trick with unpacking:

Python
langs = ["Python", "Java", "Go"]
print(*langs, sep="\n")
Output
Python
Java
Go

Reading input with input()#

input(prompt) shows the prompt, waits for the user to press Enter, and returns what they typed as a string (without the newline):

greet.py
name = input("What's your name? ")
print(f"Nice to meet you, {name}!")
Output
What's your name? Ada
Nice to meet you, Ada!

(In the output above, Ada is what the user typed.)

Converting input

Because input always returns str, doing maths on it needs a conversion:

age.py
age = int(input("How old are you? "))
print(f"In 10 years you'll be {age + 10}.")
Output
How old are you? 25
In 10 years you'll be 35.

If the user types twenty, int() raises ValueError and the program crashes. A robust program keeps asking until it gets valid input. You'll learn try/except fully later, but the pattern is simple enough to use now:

ask_number.py
while True:
    text = input("Enter a whole number: ")
    try:
        number = int(text)
        break                      # valid: leave the loop
    except ValueError:
        print(f"{text!r} isn't a whole number, try again.")

print(f"{number} squared is {number ** 2}")
Output
Enter a whole number: ten
'ten' isn't a whole number, try again.
Enter a whole number: 12
12 squared is 144

Reading several values from one line is a common need in coding exercises:

sum_line.py
numbers = [int(x) for x in input("Numbers separated by spaces: ").split()]
print(f"Sum: {sum(numbers)}, max: {max(numbers)}")
Output
Numbers separated by spaces: 4 8 15 16 23 42
Sum: 108, max: 42

Always tidy user input with .strip() (and often .lower()) before comparing it: if answer.strip().lower() in ("y", "yes"):.

Standard output vs standard error#

Every program has two output streams: stdout for normal results and stderr for errors and diagnostics. Keeping them separate lets users redirect results to a file while still seeing errors on screen.

streams.py
import sys

print("result: 42")                        # stdout
print("warning: using default config", file=sys.stderr)
Terminal
python3 streams.py > out.txt     # only "result: 42" goes into out.txt
Output
warning: using default config

Command-line arguments#

Scripts that run in terminals, cron jobs and CI pipelines take their input from the command line instead of input(). The raw arguments are in sys.argv:

args_demo.py
import sys

print(f"Script: {sys.argv[0]}")
print(f"Arguments: {sys.argv[1:]}")
Terminal
python3 args_demo.py report.csv --verbose
Output
Script: args_demo.py
Arguments: ['report.csv', '--verbose']

For anything beyond one or two arguments, use the standard library's argparse, which gives you parsing, type conversion, defaults and a free --help page:

greet_cli.py
import argparse

parser = argparse.ArgumentParser(description="Greet someone.")
parser.add_argument("name", help="who to greet")
parser.add_argument("-n", "--times", type=int, default=1, help="how many times")
parser.add_argument("--shout", action="store_true", help="use capitals")
args = parser.parse_args()

message = f"Hello, {args.name}!"
if args.shout:
    message = message.upper()
for _ in range(args.times):
    print(message)
Terminal
python3 greet_cli.py Ada --times 2 --shout
Output
HELLO, ADA!
HELLO, ADA!

Running python3 greet_cli.py --help prints an automatically generated usage page, and a wrong value (like --times abc) produces a helpful error instead of a traceback.

Exit codes#

When a program finishes, it returns an exit code to whoever started it: 0 means success, anything else means failure. Shell scripts and CI systems check it. Use sys.exit() to set it:

check_file.py
import sys
from pathlib import Path

if len(sys.argv) != 2:
    sys.exit("usage: check_file.py PATH")   # prints to stderr, exit code 1

path = Path(sys.argv[1])
if not path.exists():
    print(f"error: {path} not found", file=sys.stderr)
    sys.exit(2)

print(f"{path} is {path.stat().st_size} bytes")
Terminal
python3 check_file.py missing.txt; echo "exit code: $?"
Output
error: missing.txt not found
exit code: 2

Worked example: a tip calculator#

Putting it together — an interactive script with validated input and formatted output:

tip.py
def ask_float(prompt):
    while True:
        try:
            return float(input(prompt))
        except ValueError:
            print("Please enter a number.")


bill = ask_float("Bill amount: ")
tip = ask_float("Tip %: ")
people = int(ask_float("Number of people: "))

total = bill * (1 + tip / 100)
print(f"\nTotal with tip: {total:>10,.2f}")
print(f"Each person:    {total / people:>10,.2f}")
Output
Bill amount: 2400
Tip %: 12.5
Number of people: 3

Total with tip:   2,700.00
Each person:        900.00

Common mistakes#

  • Forgetting to convert input. input("n: ") * 2 repeats the text; it doesn't double the number.
  • Not stripping input. A stray space makes "yes " == "yes" false.
  • Printing errors to stdout. Use file=sys.stderr so errors don't pollute redirected output.
  • Using input() in scripts meant for automation. Cron jobs and CI have no keyboard; take arguments with argparse instead.

What's next#

Your programs can now talk to users. Next, let's teach them to make decisions with conditionals: if, elif, else and the match statement.

Check your understanding

Quick quiz

0/3 answered
  1. 1.What type does input() always return?

  2. 2.What does print("a", "b", sep="-", end="!") output?

  3. 3.In python3 app.py report.csv, what is sys.argv[1]?

Finished reading?

Mark this lesson complete to track your progress.