Python Module 2 – Values, variables, numbers and strings
Input and output: print(), input() and stdin
Control what print() writes with sep, end, file and flush, read and check what users type with input(), and read whole inputs from stdin for coding judges.
What you will learn
- Use sep, end, file and flush to control what print() writes
- Read user input with input() and convert it safely
- Read many lines from standard input for judge-style problems
Before you start
On this page
Every program talks to the outside world through three standard streams. It reads from standard input, writes its results to standard output, and writes error messages to standard error. In a terminal all three are connected to the terminal itself, but the shell can connect them to files or to other programs, and that is how online judges and coding tests feed a program its data and collect its answer.
The three standard streams of a program
Text description of the diagram
The diagram shows, from top to bottom, where a program's text comes from and where it goes.
- At the top is standard input (stdin): the keyboard, or a file when the program is started with < file, or the output of another program after a | pipe.
- An arrow labelled input(), sys.stdin leads from it down to your program: input() reads one line of it, sys.stdin reads it as a file.
- From your program, one arrow labelled print() leads to standard output (stdout), which is the screen, or a file after > file.
- Another arrow, labelled file=sys.stderr, leads to standard error (stderr): print(…, file=sys.stderr) writes there. It is the screen too, unless the program is started with 2> file, so error messages stay visible when the normal output goes to a file.
Writing output with print()
print() writes its arguments to standard output, turning each into text with str(). Four keyword arguments
change what it writes and where:
import sys
# By default print() puts a space between values and a line break at the end.
print("tea", "coffee", "juice")
print("tea", "coffee", "juice", sep=", ")
print("tea", "coffee", "juice", sep="")
# end replaces the line break, so the next print() carries on the same line;
# flush=True writes "Saving" out at once instead of keeping it in the buffer.
print("Saving", end="", flush=True)
print("...", end=" ")
print("done")
# Values of any type are written with str(); print() on its own writes an empty line.
print(42, 2.5, True, None, [1, 2])
print()
# file=sys.stderr sends a message to standard error instead of standard output.
print("warning: the price list is empty", file=sys.stderr) Output
tea coffee juice tea, coffee, juice teacoffeejuice Saving... done 42 2.5 True None [1, 2]
Printed as an error (standard error)
warning: the price list is empty
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 print_options.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
sepgoes between the values (a space unless you say otherwise), andsep=""glues them together.endis written after the last value (a line break unless you say otherwise).end=""orend=" "lets the nextprint()carry on the same line.file=sys.stderrsends the text to standard error. The output above shows it under its own label: error messages stay visible on the screen even when a user saves the normal output in a file with> results.txt, and they do not end up mixed with the results.flush=Truemakes Python write the text at once, as the program does for “Saving”. Output is normally collected in a buffer first: a line at a time in a terminal, and in larger pieces when it goes to a file or a pipe. So a progress message printed withend=""may appear late unless you addflush=True, as inprint("Working…", end="", flush=True), and lines on standard output and standard error can come out in a different order from the one the program wrote them in.
Commas in a print() call are often all you need to join values: print("Total:", 5) works where
print("Total: " + 5) raises TypeError, because + cannot add a number to a string. An f-string gives you full
control over the layout.
Reading a line with input()
input() waits for one line of input and returns it as a string, without the line break at the end. With an
argument, it first writes that prompt to standard output, without a line break. Whatever the user types is text,
even 29, so a number must be converted, and the conversion must be checked, because people mistype:
name = input("Your name: ").strip()
# Ask again until the answer is a whole number.
while True:
text = input("Your age: ")
try:
age = int(text)
break
except ValueError:
print(f"{text!r} is not a whole number, try again.")
print(f"Hello, {name}! Next year you will be {age + 1}.") Input (standard input)
Kavya twenty 29
Output
Your name: Your age: 'twenty' is not a whole number, try again. Your age: Hello, Kavya! Next year you will be 30.
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 ask_age.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
.strip()removes spaces the user typed by accident.int()ignores spaces and a line break around the digits by itself, so" 29"is read as 29.int(text)raisesValueErrorfor text that is not a whole number, such as"twenty". Thetryblock catches it, explains the problem and asks again; thewhile Trueloop (the control-flow lessons cover loops) ends withbreakonce a number has been read.- The output looks run together because the answers came from the input shown above it, not from a keyboard:
input()writes each prompt and then reads a line without printing it. In a terminal, the user’s typing is shown by the terminal itself, so each answer appears after its prompt.
Note
The code runners of this site cannot pause a program to wait for your typing, so they give it all of its input
before it starts. The Run button on this page uses the input shown above the output, and the Python Online
Compiler has an Input box where you type every line before you press Run. In both, input() reads those lines in
order, one per call.
When the input runs out
When there is nothing left to read, input() raises EOFError (EOF is short for end of file):
first = input()
print("Read:", first)
# There is no second line, so input() raises EOFError.
second = input()
print("Read:", second) Input (standard input)
first line
Output (exit status 1)
Read: first line
Printed as an error (standard error)
Traceback (most recent call last):
File "end_of_input.py", line 5, in <module>
second = input()
EOFError: EOF when reading a line
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 end_of_input.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
When you type the input in a terminal, you end it by pressing Ctrl-D (macOS and Linux) or Ctrl-Z followed by Enter
(Windows). A program that reads until the end of its input should not count on a fixed number of input() calls;
the next section shows the usual ways.
Reading many lines: judge-style input
Online judges and coding tests give a program all of its input on standard input and compare what it prints with the expected answer. Two patterns cover most problems. The first reads everything at once:
import sys
# Read everything at once and split it into words, whatever the line breaks.
words = sys.stdin.read().split()
total = 0
for word in words:
total += int(word)
print(len(words), "numbers, total", total) Input (standard input)
5 10 20 30 40 50
Output
6 numbers, total 155
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 sum_all.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
sys.stdin.read() returns the whole input as one string, and split() cuts it into words on spaces and line breaks
alike, so the program does not care how the numbers are spread over lines. The second pattern goes line by line:
import sys
# A for loop over sys.stdin reads one line at a time and stops at the end of the input.
for line in sys.stdin:
print(repr(line), "->", line.rstrip("\n").upper())
# readline() returns "" once the input has run out, instead of raising EOFError.
print(repr(sys.stdin.readline())) Input (standard input)
tea chai latte
Output
'tea\n' -> TEA 'chai latte\n' -> CHAI LATTE ''
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 line_by_line.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
A for loop over sys.stdin gets one line per turn, each with its "\n" still on the end (which is what repr()
makes visible; only the last line can lack it, when the input does not end with a line break), and stops when the
input ends, without an EOFError. sys.stdin.readline() reads a single line and returns an empty string once there
is nothing left. On your own computer, you can feed a program a whole file exactly as a judge does:
python3 solve.py < input.txt (py solve.py < input.txt in the Windows Command Prompt). PowerShell has no < for
input, so there you pipe the file in instead: Get-Content input.txt | py solve.py.
Never eval() what a user types
eval(text) runs text as a Python expression. You may see eval(input()) used to read a number or a list, but
it runs anything the user types, and an expression can import modules, read files and delete them. Convert
numbers with int() or float(), which accept numbers and nothing else.
For text that holds a Python literal, such as a list or a dictionary, ast.literal_eval() reads the value and
refuses anything that would run code:
import ast
# literal_eval() reads Python literals (numbers, strings, lists, dictionaries …) and nothing else.
print(ast.literal_eval("[3, 1, 2]"))
print(ast.literal_eval("{'tea': 20, 'coffee': 30}"))
# Anything that would run code is refused, where eval() would have run it.
try:
ast.literal_eval("__import__('os').getcwd()")
except ValueError as error:
print("refused:", type(error).__name__) Output
[3, 1, 2]
{'tea': 20, 'coffee': 30}
refused: ValueError
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 literal_eval.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
Security
Treat everything a program reads, from a user, a file or the network, as untrusted. Convert it with a function that
accepts only the format you expect, limit its size, and handle the error when it does not fit. Even
ast.literal_eval(), which runs no code, is not recommended by its documentation for untrusted data: a small
crafted input can use up memory or crash the interpreter. Keep it for text you trust, such as a value your own
program wrote, and use a data format such as JSON (a later lesson) for data from outside.
Key takeaways
print()writes to standard output;sepgoes between values,endafter them,file=sys.stderrsends error messages to standard error andflush=Truewrites at once.input()returns a string without the line break; convert it withint()orfloat()insidetryand handleValueError.- At the end of the input,
input()raisesEOFError, while a loop oversys.stdinsimply stops. - For judge-style input,
sys.stdin.read().split()reads every value at once, and aforloop oversys.stdinreads line by line. - Never pass user input to
eval(). Convert numbers withint()orfloat(), and keepast.literal_eval()for literals from a source you trust.
Exercise
Exercise · Easy · Python
Read marks from judge-style input
Online judges and coding tests give a program its data on standard input in a fixed layout. In this one, the first line holds n, the number of students, and the second line holds their n marks, separated by spaces:
3
70 80 95
Write read_marks(lines), which takes the lines of such an input and returns the average mark, rounded with round(average, 2). For the input above it returns 81.67.
linescan be a list of strings such as["3", "70 80 95"], or an open file such assys.stdinor anio.StringIO, whose lines still end with"\n". A program would callprint(read_marks(sys.stdin)).- The numbers may have extra spaces around them, and lines after the second are ignored.
- Raise
ValueErrorwhen the second line is missing, whennis less than 1, when the second line does not hold exactlynmarks, or when a mark is not a whole number, such as80.5oreighty.
The sample tests import your function from marks.py.
Starter code · marks.py
def read_marks(lines):
"""Return the average of the n marks on the second line, rounded to two decimals."""
# Replace this line with your code.
return 0.0 The sample tests · test_marks.py
import io
from marks import read_marks
def raises_value_error(lines):
"""True when read_marks(lines) raises ValueError."""
try:
read_marks(lines)
except ValueError:
return True
return False
def test_lists():
"""averages the marks of a list of lines"""
assert read_marks(["3", "70 80 95"]) == 81.67
assert read_marks(["4", "10 20 30 40"]) == 25.0
assert read_marks(["1", "100"]) == 100.0
def test_files():
"""reads lines that end with a line break, as a file gives them"""
assert read_marks(io.StringIO("3\n70 80 95\n")) == 81.67
assert read_marks(io.StringIO(" 2 \n 50 61 \n")) == 55.5
def test_extra_lines():
"""ignores the lines after the second"""
assert read_marks(["2", "40 60", "not a mark"]) == 50.0
def test_wrong_count():
"""raises ValueError when the number of marks is not n"""
assert raises_value_error(["3", "70 80"])
assert raises_value_error(["2", "70 80 90"])
def test_missing_line():
"""raises ValueError when there is no second line"""
assert raises_value_error(["3"])
assert raises_value_error([])
def test_bad_values():
"""raises ValueError for n below 1 and for marks that are not whole numbers"""
assert raises_value_error(["0", ""])
assert raises_value_error(["-1", "5"])
assert raises_value_error(["2", "70 eighty"])
assert raises_value_error(["2", "70 80.5"]) A hint
list(lines) turns a list, a file or an io.StringIO into a list of its lines, so you can check its length and take rows[0] and rows[1]. int() ignores spaces and the "\n" around a number, split() with no argument does the same for the marks, and int("eighty") raises the ValueError you need without any extra check.
Results of the sample tests
| Test | Result | Details |
|---|
What your code printed
The sample tests run on this device, in your browser (Pyodide): nothing is sent to mysmartcopilot.com. The first run downloads Python (about 13.5 MB), which is kept for the next runs. A check in your browser is feedback for you, not proof that the code is right for every input.
Check yourself
5 questions about this lesson. Every answer and why it is right is on the page, behind “Show the answer”. Your score stays in this browser.
References
- print() (Built-in Functions) (Python Software Foundation)
- input() (Built-in Functions) (Python Software Foundation)
- sys.stdin, sys.stdout and sys.stderr (sys, System-specific parameters and functions) (Python Software Foundation)
- ast.literal_eval() (ast, Abstract Syntax Trees) (Python Software Foundation)
- eval() (Built-in Functions) (Python Software Foundation)
- The Python Tutorial: Input and Output (Python Software Foundation)
- The Python Tutorial: Invoking the Interpreter (the end-of-file character) (Python Software Foundation)
- about_Redirection (PowerShell) (Microsoft)
Related tools
Report a problem with this lesson
Kept only in this browser. Your Learn progress