CoursePython from Scratch to Intermediate · Module 1: Getting Started · part 9 of 75
Part 9 · Module 1: Getting Started

Lesson 2: Trying lines out and saving them as scripts

14 min read·14 Oct 2026
Module 1 · Lesson 2 · About 40 minutes · Needs: Lesson 1 (running a cell, print, reading the last line of an error)

The situation

Amira wants a card for one book on the shelf. Before you write the card, you need the numbers on it. Jonah borrowed Frankenstein (loan L04) on 14 September. Until Module 7 brings real dates, the course counts shelf days: days since the shelf opened, so 14 September is day 14 and today, Wednesday 14 October, is day 44. A loan lasts 14 days. When is Jonah's book due, and how late is it?

You will work it out one line at a time, then save the lines in a file, so the same answer comes out every time.

A real case, first

The place where you type Python one line at a time is called the interactive prompt. In 2024 Python's core developers replaced it. PEP 762, "REPL-acing the default REPL" (2024), describes the new prompt that arrived in Python 3.13: it shows colour, and it makes editing several lines at once much easier. A PEP (Python Enhancement Proposal) is the public document that proposes and explains a change to Python.

That matters to you because Colab runs Python 3.12, so you see the older, plainer prompt. In 3.12, typing exit on its own does not leave the prompt; it prints a hint telling you to type exit() instead. In 3.13 and later, exit alone works. This lesson's transcripts were captured on 3.12. The general point: your Python version decides small details of what you see, so knowing it is part of reading any output.

What you will be able to do

  • Tell an expression from a statement, and predict what each shows at the prompt
  • Use the interactive prompt to test a line before you keep it
  • Write a script file with %%writefile and run it with !python
  • Indent a block correctly and read the three common indentation errors
  • Check which Python you are running, in Colab and on your own computer

1. Expressions and statements (Essential)

Every line of Python you will ever write is built from two kinds of piece. Knowing which is which tells you, before you run anything, whether a line will show you a result.

At the prompt As a script >>> 14 + 14 28 >>> 44 - 28 16 card.py 4 lines of print runs the whole file one line, answer at once | many lines, run together
Python can be used two ways: one line at a time at the prompt, or a whole saved file at once as a script. Blue marks your own code throughout.

At the interactive prompt you type one line, and Python answers at once. In a script you write many lines into a file, and Python runs the whole file. The difference between them starts with expressions.

14 + 14 an expression works out 28 one value Jonah's due day: borrowed day 14, plus 14 days
An expression is code that works out to one value: 14 + 14 becomes 28, Jonah's due day. Green marks a correct result.

An expression is a piece of code that Python works out to a single value. 14 + 14 is an expression: Python adds the numbers and the value is 28. That is Jonah's due day: borrowed on day 14, plus 14 days of loan. The + adds, - takes away, and * multiplies; Module 2 covers the rest.

print( 44 - 28 ) the whole line: a statement (does something) inside: an expression, worth 16 import sys is a statement with no expression in it
A statement is one complete instruction; print(44 - 28) is a statement with the expression 44 - 28 inside it.

A statement is one complete instruction: a line that Python carries out. print(44 - 28) is a statement. Inside its brackets sits the expression 44 - 28, which works out to 16, the number of days Jonah is late. import sys is a statement too, and it holds no expression at all. Statements do things; expressions produce the values they use.

Here is the same idea in a Colab cell. A cell shows the value of its last line underneath.

bare expressions print 14 + 14 44 - 28 16 print(14 + 14) print(44 - 28) 28 16 only the last line shown every print shown
A Colab cell shows the value of its last line only; print shows a value whichever line it is on.
python
14 + 14
44 - 28

Code walkthrough

  • Line 1 is an expression. Python works out 28, but it is not the last line, so nothing is shown.
  • Line 2 is the last line, so Colab shows its value.

Output

text
16

Only one number appeared. To see more, use print, which shows its value on any line.

python
print(14 + 14)
print(44 - 28)

Code walkthrough

  • Each line is a statement. The expression inside the brackets is worked out first, then print shows the result.

Output

text
28
16

2. The interactive prompt, the REPL (Essential)

The prompt is where you try things. When you are not sure what a line does, typing it at the prompt and seeing the answer is quicker than reasoning about it.

Read your line Evaluate work it out Print show the value Loop wait again >>> 14 + 14 then 28 then >>> again
The REPL reads your line, evaluates it, prints the value and loops back to wait for the next line.

The prompt has a name: the REPL, short for read, evaluate, print, loop. Python reads the line you type, evaluates it (works it out), prints the result, and loops back to wait for the next line. A Colab cell behaves like a REPL that takes several lines at once.

>>> if 44 > 28: ... print("overdue") ... overdue >>> new line Python waits ... more of the same line type what comes after the symbols, not the symbols
>>> means Python is waiting for a new line; ... means it is waiting for more of the instruction above, here the block after the colon.

The REPL marks its lines with symbols. >>> is the prompt: Python is waiting for a new line. ... means Python is waiting for more of the same instruction, because the line above ended with a colon. You type what comes after the symbols, never the symbols themselves. Here is a real session, captured on Python 3.12:

text
>>> 14 + 14
28
>>> 44 - 28
16
>>> print(44 - 28)
16
>>> import sys
>>>

Each expression was echoed straight back. print showed its value. import sys is a statement with no value, so Python showed nothing and gave a new prompt.

Echo at the prompt print >>> "Frankenstein" 'Frankenstein' >>> print("Frankenstein") Frankenstein for you: quotes kept for readers: plain text
The prompt echoes a value the way Python writes it, quotes included; print shows the text the way a reader sees it. Grey marks a background helper.

There is one small difference between echoing and printing. Type text in quotation marks and the REPL echoes it the way Python writes it, quotes included. print shows it the way a person reads it:

text
>>> "Frankenstein"
'Frankenstein'
>>> print("Frankenstein")
Frankenstein

The echo is for you, checking a value. print is for the people who read the output, like Amira.

3. Writing a script file with %%writefile (Essential)

Lines typed at the prompt vanish when you close it. A file keeps them, so Amira gets the same card tomorrow without anyone retyping it.

%%writefile card.py print("Franken... print("Loan L04... ... saved, not run card.py a file in Colab's folder Colab says: Writing card.py
%%writefile on a cell's first line saves the rest of the cell as a file instead of running it.

A script is a plain text file of Python code whose name ends in .py. In Colab you make one with %%writefile. It is a cell magic: a command for the notebook, not Python, which is why it starts with two percent signs. It must be the very first line of the cell, and it saves the rest of the cell into the named file instead of running it.

python
%%writefile card.py
print("Frankenstein by Mary Shelley")
print("Loan L04, Jonah, borrowed on day", 14)
print("Due on day", 14 + 14)
print("Days late on day 44:", 44 - 28)

Code walkthrough

  • %%writefile card.py names the file. Nothing below it runs yet; it is only saved.
  • Each print line is a statement. A comma inside print separates two values, and print puts a space between them.
  • 14 + 14 and 44 - 28 are expressions inside the statements, worked out when the script runs.

Output

text
Writing card.py
card.py name ends in .py 1 print("Frankenstein by Mary Shelley") 2 print("Loan L04, Jonah, borrowed on day", 14) 3 print("Due on day", 14 + 14) 4 print("Days late on day 44:", 44 - 28)
A script is plain text with a name ending in .py: card.py is four print lines, nothing more.

The file now sits in Colab's working folder. Click the folder icon in the left sidebar to see card.py. Running the cell again prints Overwriting card.py and replaces the file.

4. Running a script with python (Essential)

A saved file does nothing until you run it. Running it is how the card gets printed, and later how Amira's whole morning report will run from one command.

!python card.py in a cell python reads the file Frankenstein by Mary Shelley Loan L04, Jonah, ... day 14 Due on day 28 Days late on day 44: 16 ! goes to the command line
!python card.py hands the file to a fresh Python, which runs it and shows the four lines of the card.

!python card.py runs the file. The ! at the start sends the line to the computer's command line, outside the notebook. There, python is the program that runs Python files, and card.py is the file to give it.

python
!python card.py

Code walkthrough

  • ! means "this is a command for the computer, not Python code".
  • python card.py starts a fresh Python, which reads the file and runs it.

Output

text
Frankenstein by Mary Shelley
Loan L04, Jonah, borrowed on day 14
Due on day 28
Days late on day 44: 16
line 1 Frankenstein... line 2 Loan L04... line 3 Due on day 28 line 4 Days late... 16 then this Python stops and forgets everything
A script runs from the first line to the last, in order, once, so the same file gives the same card every time.

A script runs from its first line to its last, in order, once, then that Python stops. So the same file gives the same four lines every time.

Break it: an expression with no print

At the prompt, 44 - 28 showed 16. In a script, nobody is there to see an echo, so a bare expression is worked out and thrown away.

at the prompt in silent.py >>> 44 - 28 16 14 + 14 44 - 28 output: nothing echoed back
A bare expression in a script is worked out and thrown away: only print shows anything. Red marks a failure.
python
%%writefile silent.py
14 + 14
44 - 28

Code walkthrough

  • Two bare expressions, with no print, saved as silent.py.

Output

text
Writing silent.py
python
!python silent.py

Code walkthrough

  • Python runs both lines without complaint and works out both values. It shows nothing at all: the output area stays empty.

The fix is to wrap each value in print. A script shows only what you print.

5. Indentation and whitespace rules (Essential)

Python is unusual: the spaces at the start of a line are part of its grammar. Get them wrong and the script does not run at all, so this is worth five careful minutes now.

print("Shelf check for loan L04") if 44 > 28: print("Overdue") print("Days late:", 44 - 28) print("Check finished") colon opens a block 4 spaces in: the block back at the edge: ended
A line ending in a colon opens a block; the lines indented four spaces under it are the block, and the first line back at the edge ends it.

Some lines end in a colon, :. A colon means "a group of lines follows". That group is called a block, and you mark which lines belong to it by indenting them: moving them right with spaces. The if line below asks whether 44 is greater than 28 (> means "greater than"); Module 4 teaches if properly. For now, watch the shape.

python
print("Shelf check for loan L04")
if 44 > 28:
    print("Overdue")
    print("Days late:", 44 - 28)
print("Check finished")

Code walkthrough

  • Line 1 is not indented, so it always runs.
  • Line 2 ends in a colon. It opens a block.
  • Lines 3 and 4 start with four spaces, so they are the block. They run only if the if is true, and it is.
  • Line 5 is back at the left edge, so the block has ended.

Output

text
Shelf check for loan L04
Overdue
Days late: 16
Check finished
inside a line at the start 44-28 44 - 28 the same: both 16 print(16) print(16) two spaces: second fails spaces are for readers spaces are grammar
Spaces inside a line are for people and change nothing; spaces at the start of a line are grammar.

Whitespace means spaces, tabs and line breaks. Inside a line, Python ignores extra spaces: 44-28 and 44 - 28 are the same. At the start of a line, spaces are counted.

four spaces a tab, then spaces if 44 > 28: print("a") Colab types these for you if 44 > 28: tab print("a") print("b") TabError
Indent with four spaces per level; a tab and spaces mixed in one block stop Python with a TabError.

Use four spaces for each level of indent. That is the rule in PEP 8, Python's style guide, and Colab inserts four spaces for you when you press Enter after a colon. A tab is a different, invisible character. Mixing tabs and spaces in one block makes Python stop with a TabError, so use spaces only.

last line of the error what you did unexpected indent a line is indented with nothing above to belong to expected an indented block nothing is indented under a colon inconsistent use of tabs tabs and spaces mixed (a TabError)
The last line of an indentation error names one of three mistakes, and each has one fix.

Three mistakes cause almost every indentation error, and the error's last line names which one you made. Two of them, at the prompt:

text
>>>   print(16)
  File "<stdin>", line 1
    print(16)
IndentationError: unexpected indent
>>> if 44 > 28:
... print("overdue")
  File "<stdin>", line 2
    print("overdue")
    ^^^^^
IndentationError: expected an indented block after 'if' statement on line 1

The first line was indented with nothing above to belong to. The second forgot to indent the block under the colon.

Break it: one missing indent sinks the whole script

broken.py 3 lines check grammar whole file first IndentationError line 3 line 1 was fine, and it still never printed
Python checks the grammar of the whole script before running any line, so one bad indent means nothing runs at all.

Save the check as a script, but leave out the indent under the colon.

python
%%writefile broken.py
print("Shelf check for loan L04")
if 44 > 28:
print("Overdue")

Code walkthrough

  • Line 3 should be indented under the if on line 2, and it is not.

Output

text
Writing broken.py
python
!python broken.py || echo "Python reported a failure"

Code walkthrough

  • !python broken.py runs the script, as before.
  • || is a command-line word for "if the command on the left fails, run the one on the right". echo prints its text. So the last line appears only because Python reported a failure.

Output

text
  File "/content/broken.py", line 3
    print("Overdue")
    ^^^^^
IndentationError: expected an indented block after 'if' statement on line 2
Python reported a failure

Look at what is missing: the first line, Shelf check for loan L04, never printed, although it was correct. Python reads the whole file and checks its grammar before it runs any line. One bad indent stops everything. The fix is four spaces before print("Overdue").

6. Which Python am I running (Recommended)

Different Python versions differ in small ways, as the real case showed. When your output does not match a lesson's, the version is the first thing to check.

3 . 12 . 15 major Python 3 minor new features patch bug fixes only the course is written for 3.12
In 3.12.15 the first two numbers, 3.12, decide which features you have; the last only counts bug fixes.

A Python version has three numbers. In 3.12.15, 3 is the major version, 12 the minor version and 15 the patch. New features arrive with a new minor version; a patch only fixes bugs. So 3.12 is what matters, and the course is written for it.

python
import sys
print(sys.version_info)

Code walkthrough

  • import sys brings in sys, the part of Python that knows about Python itself. Module 7 explains import.
  • sys.version_info holds the version of the Python running this notebook, as named parts.

Output

text
sys.version_info(major=3, minor=12, micro=15, releaselevel='final', serial=0)

Python calls the patch number micro. Yours may show a different patch number; major=3, minor=12 is what to check. You can also ask the command line:

python
!python --version

Code walkthrough

  • --version asks the python program for its version and nothing else. This is the Python that !python card.py used.

Output

text
Python 3.12.15
Python 3.12 (Colab) Python 3.13 and later plain text prompt exit alone prints a hint type exit() to leave colour in the prompt easier multi-line editing exit alone works PEP 762 (2024) describes the new prompt
Colab's Python 3.12 has the plain prompt; 3.13 and later bring the newer one from PEP 762, but the course code runs the same on both.

If either shows 3.13 or higher, the course still works, because it uses nothing later versions removed. You would notice the newer prompt from PEP 762.

7. Running Python on your own computer (Recommended)

Colab is a borrowed computer. Sooner or later you will want Python on your own, where files stay put. Nothing here is needed for the course.

terminal your computer python3.12 starts the REPL python3.12 card.py runs a script >>> exit() leaves the card 4 lines Windows: py -V:3.12 in place of python3.12
On your own computer a terminal gives the same two ways: python3.12 for the prompt, python3.12 card.py for a script.

On your own computer you use a terminal: a window where you type commands, the same kind of command ! sends in Colab. Install Python 3.12 by following 07-run-locally.md. Then, in a terminal (on Windows, type py -V:3.12 wherever this shows python3.12):

text
python3.12 --version
python3.12
python3.12 card.py

These were not run in Colab; they come from the course's run-locally page. The first prints the version. The second starts the REPL; type exit() to leave. The third runs a script in the terminal's current folder. Only the ! is gone.

In production

Working programmers use both modes daily. The REPL is a scratch pad: try one expression, check a value, copy the line that works into a file. Scripts are what runs for real, because a file can be shared, reviewed and run again the same way. Python's own tutorial opens the same way, with starting the interpreter and using it interactively (Python tutorial, "Using the Python Interpreter"). Indentation is part of the language definition, so code editors insert four spaces automatically. When two people get different output from one script, comparing versions comes first.

What you added to the Booknook shelf

  • Jonah's due day (28) and days late (16) for loan L04, worked out at the prompt
  • card.py, a four-line script that prints Frankenstein's card the same way every run
  • A habit of checking the version and reading an indentation error's last line

Check yourself

  1. In a Colab cell holding 14 + 14 on line 1 and 44 - 28 on line 2, what appears, and why?

Only 16. A cell shows the value of its last line only; the first expression is worked out and not shown.

  1. You save 44 - 28 alone in days.py and run !python days.py. What do you see?

Nothing. A script never echoes values; it shows only what you print.

  1. What does ... at the start of a REPL line mean?

Python is waiting for more of the same instruction, usually the block under a line that ended in a colon.

  1. A script's first line is correct, but line 3 has a missing indent. Does line 1 print?

No. Python checks the grammar of the whole file before running any of it, so the IndentationError stops every line.

Exercise

Kwame's loan L21 of Pride and Prejudice started on shelf day 26. Write a script due.py with %%writefile that prints exactly these two lines, working the numbers out with expressions inside print (due day is borrow day plus 14; days late is 44 minus the due day):

text
Due on day 40
Days late on day 44: 4

Then run this check cell. Paste it as it is: it runs your script and compares what it prints with the two lines above. Module 10 explains how.

python
import subprocess, sys
result = subprocess.run([sys.executable, "due.py"], capture_output=True, text=True)
print(result.stdout == "Due on day 40\nDays late on day 44: 4\n")

Code walkthrough

  • subprocess.run runs due.py with the same Python as the notebook and keeps what it prints in result.stdout.
  • == asks "are these two the same?". \n inside the quotes stands for the end of a line. The check prints True when your output matches exactly, and False when it does not (or when due.py does not exist yet).
python
%%writefile due.py
print("Due on day", 26 + 14)
print("Days late on day 44:", 44 - 40)

Code walkthrough

  • Two statements, each with an expression inside. Run !python due.py, then the check cell again: it prints True.

Key terms

TermMeaning
ExpressionA piece of code that works out to one value, such as 14 + 14
StatementOne complete instruction that Python carries out, such as print(44 - 28)
REPLRead, evaluate, print, loop: Python's interactive prompt
Prompt>>>, the sign that the REPL is waiting for a line; ... means "more of the same instruction"
ScriptA text file of Python code ending in .py, run from top to bottom
Cell magicA notebook command starting with %%, such as %%writefile
BlockThe indented lines under a line that ends in a colon
IndentationSpaces at the start of a line; four per level, never tabs
WhitespaceSpaces, tabs and line breaks
VersionThree numbers, major.minor.patch, such as 3.12.15
TerminalA window on your own computer where you type commands

Sources

  • Python core developers, PEP 762, "REPL-acing the default REPL", 2024. https://peps.python.org/pep-0762/
  • Python Software Foundation, "What's New In Python 3.13", 2024. https://docs.python.org/3/whatsnew/3.13.html
  • Python Software Foundation, Python tutorial, "Using the Python Interpreter" (Python 3.12 documentation). https://docs.python.org/3.12/tutorial/interpreter.html
  • Python Software Foundation, The Python Language Reference, "Lexical analysis: Indentation" (Python 3.12 documentation). https://docs.python.org/3.12/reference/lexical_analysis.html#indentation
  • Guido van Rossum, Barry Warsaw and Alyssa Coghlan, PEP 8, "Style Guide for Python Code", 2001. https://peps.python.org/pep-0008/