Learn
05.1 | TEXT FILES AND CONTEXT MANAGERS
01 | MEMORY ENDS, FILES REMAIN
Your quiz scoreboard lived in a list while Python was running. When the process ended, that in-memory list disappeared. A file stores bytes outside the process so a later run can read them. This is persistence.
A text file is a useful first step: save a short message, reopen it and display it. Saving a Python source file and saving a program’s data are separate operations. An editor stores instructions; your running program can store the information it produces.
Work in a new practice folder and use the filenames shown. The examples deliberately create or change those practice files. Before choosing a write mode for an existing file, decide whether replacing its current contents is intended.
02 | OPEN CONNECTS YOUR PROGRAM TO A FILE
open() returns a file object. It provides methods such as read() and write(), tracks a current position and manages a connection to the operating system. The filename identifies the resource; the file object is the program’s working handle.
The mode tells Python what operation you want. "r" reads an existing file; "w" writes and truncates an existing file as soon as opening succeeds; "a" writes at the end; "x" creates a new file and fails if it already exists. "w", "a" and "x" can create a file when the parent folder exists.
A relative filename such as notes.txt is interpreted relative to the current working directory. That is not always the folder containing your script. The pathlib lesson will make locations explicit.
| Mode | Main purpose | Existing file | Missing file |
|---|---|---|---|
| r | Read | Preserved | FileNotFoundError |
| w | Write from beginning | Truncated on open | Created |
| a | Append | New writes go to end | Created |
| x | Exclusive creation | FileExistsError | Created |
03 | WITH MANAGES THE LIFETIME
A context manager manages setup and cleanup around a block. With a file, the with statement opens the resource and closes it when the block finishes, including when an exception leaves that block. The name after as is bound to the file object.
The indented body is the period during which this file is open. A file.close() call after an ordinary block can be skipped when an earlier operation fails; with gives the cleanup a reliable structure. Closing also flushes Python’s buffered writes, but it is not a guarantee against every disk failure or power loss.
The file variable still exists after the block, but its file object is closed. Trying another read or write through that closed object raises ValueError. A new operation needs another open.
with open("notes.txt", "w", encoding="utf-8") as file:
file.write("One useful idea\n")
print("Closed:", file.closed)EXPECTED OUTPUT
Closed: True
04 | WRITE TEXT AND ADD LINE ENDINGS
write() accepts text in text mode. It does not add a line ending automatically. The escape sequence \n represents a newline character inside a Python string. Writing two strings without a separator joins their characters in the file.
The return value from write() is the number of characters accepted by the text stream, not necessarily the number of encoded bytes on disk. Text such as café can use more bytes than characters in UTF-8.
Use encoding="utf-8" explicitly so your program follows a predictable text encoding rather than depending on a platform default. Encoding converts characters to bytes; decoding converts stored bytes back to characters.
with open("notes.txt", "w", encoding="utf-8") as file:
written = file.write("Learn one idea\n")
file.write("Test it yourself\n")
print("First write characters:", written)EXPECTED OUTPUT
First write characters: 15
05 | READ ALL TEXT OR ONE LINE AT A TIME
read() returns the remaining text from the current file position. For a small file, that is convenient. Iterating over the file yields lines without first loading the entire file into one string, which can suit larger files.
A line read from a text file usually includes its terminating newline. print(line) then adds another newline, causing apparent blank gaps. Use print(line, end="") to display the existing line ending without adding another.
readline() returns one line or an empty string at end of file. A blank line containing a newline is not the same as the end-of-file empty string. These differences matter when processing records.
with open("notes.txt", "w", encoding="utf-8") as file:
file.write("Learn\nTest\n")
with open("notes.txt", "r", encoding="utf-8") as file:
for line in file:
print(line, end="")EXPECTED OUTPUT
Learn Test
06 | A READ ADVANCES THE POSITION
Reading consumes characters from the stream’s current position. After read() reaches the end, another read() returns empty text. It does not restart automatically. Reopen the file when you want a simple fresh read.
seek(0) moves to the beginning. In text mode, do not treat every seek offset as a freely chosen byte or character index; encodings and newline translation make arbitrary positioning more complicated. This lesson uses only the simple reset to zero.
Do not mistake an empty second read for an empty file. Ask where the stream position is and whether another operation has already consumed its contents.
with open("notes.txt", "w", encoding="utf-8") as file:
file.write("ROBOT")
with open("notes.txt", "r", encoding="utf-8") as file:
print(repr(file.read()))
print(repr(file.read()))
file.seek(0)
print(repr(file.read()))EXPECTED OUTPUT
'ROBOT' '' 'ROBOT'
07 | APPEND WITHOUT REPLACING EARLIER NOTES
Append mode sends new writes to the end rather than clearing earlier text. It suits a simple log or a growing list of lines. It does not inspect whether the current last line already ends with a newline.
If a file ends with hello and you append world, the result is helloworld. Design a consistent record separator and write it yourself. Append is not the same as editing an arbitrary existing record.
The example first deliberately writes a known practice file, then appends one more line. In an application, repeatedly running the append operation can create repeated entries; decide whether that is intended.
with open("notes.txt", "w", encoding="utf-8") as file:
file.write("First note\n")
with open("notes.txt", "a", encoding="utf-8") as file:
file.write("Second note\n")
with open("notes.txt", "r", encoding="utf-8") as file:
print(file.read(), end="")EXPECTED OUTPUT
First note Second note
08 | TRIM ONLY WHAT YOU MEAN TO TRIM
strip() removes leading and trailing whitespace, not just a newline. That is useful for a menu response but can erase meaningful spaces from a text record. For a line ending, line.rstrip("\n") removes trailing newline characters while preserving surrounding spaces.
Ordinary text reading uses universal newline handling, so common line endings are normally presented as \n. If a format has stricter requirements, design its parsing explicitly. Do not use broad trimming simply because output looks untidy.
A text file stores characters, not automatic Python types. Reading "12" gives text until you choose a conversion and validate it. The next lesson introduces structured formats with clearer record boundaries.
09 | COMPARE FILE MODES IN A SAFE MODEL
This browser model begins with a pretend file containing First note followed by a newline. It shows what different modes do without accessing your computer’s files. Reset restores the initial content.
10 | HANDLE FAILURE WITHOUT HIDING IT
Opening can fail because a path is missing, permissions do not allow access or the storage is unavailable. A context manager closes an opened file; it does not make every operation succeed or suppress every exception.
In the validation lesson, you will catch specific failures where the application can give useful feedback or recover. A missing optional data file might mean a new tracker. A damaged existing save file must not automatically be treated as an empty tracker and overwritten.
Keep the distinction between data in memory, a write accepted by Python, a closed file and a later successful reload. Testing persistence means ending or resetting the in-memory state and reading the saved data again.
PUT YOUR SKILLS TO WORK
Use the Section 5 challenges to practise these ideas independently. Work in your Python editor, predict results and keep a short test record.
Section 5 challenges Python course navigation