CHAPTER 21 · INTERMEDIATE4 min read

Paths and Text Files

Treat file locations, text encodings, and resource lifetimes as deliberate parts of your program.

Python 3.12+Free to readModule 5 of 13
YOUR NEXT SMALL WINS

By the end, you’ll be able to…

  • Build portable paths with pathlib.
  • Choose safe text-reading and writing strategies.
  • Distinguish missing files, empty content, and decoding failures.

01A path describes a location

A filename such as notes.txt is relative to the process working directory. That directory might be your project while developing, a scheduler directory tomorrow, or a temporary folder in a test. A script does not automatically resolve relative paths beside its source file. Accept a base directory from the caller, or deliberately derive one, instead of assuming how the program was launched.

Use pathlib.Path to join components with the / operator. This expresses a filesystem operation without hard-coding a slash convention. Path objects are descriptions: constructing one neither creates the directory nor proves that a file exists. Separate choosing the location from opening it so both decisions remain visible.

paths.py🐍Python
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.

02Text is decoded bytes

A file stores bytes. Text mode decodes those bytes into strings and encodes strings when writing. Specify UTF-8 when that is your data contract; relying on a machine-specific default can turn a working import into a deployment failure. An encoding error is evidence that the bytes and chosen contract disagree. Silently ignoring undecodable bytes can corrupt names, identifiers, or quantities.

read_text is convenient for a small configuration or report. For a large export, iterate over an opened file so the whole document need not fit in memory. The with statement closes the handle even if processing a line raises an exception. Strip only what the task requires: rstrip("\n") removes newline characters, whereas strip() also discards meaningful surrounding whitespace.

lines.py🐍Python
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.

03Write with an explicit replacement policy

Writing with write_text or open(..., "w") replaces existing content. Appending with "a" preserves previous content but can repeat records if a job is retried. Choose the behavior from the application requirement before selecting the mode. For a new-only output, mode "x" refuses to overwrite an existing file.

A check such as if not path.exists() followed by opening does not guarantee that another process cannot create the file between those operations. Opening in the desired mode lets the filesystem enforce the relevant condition. Similarly, catch FileNotFoundError around the operation when a missing input has a defined recovery path.

04Make file behavior testable

Pass Path values into a function rather than burying a global filename in its body. A test can then supply a temporary directory, inspect the result, and let cleanup happen automatically. Return a useful value, such as the number of records written, so callers can verify behavior without scraping printed messages.

An empty file is valid content in some workflows; a missing file is an access failure; malformed text is a format failure. Keep these cases distinct. If you catch all three and return an empty list, downstream code can report a successful zero-record import when the input was never read. Good file handling preserves enough information to make that difference observable.

LET IT CLICK

The ideas worth keeping.

  • Resolve paths deliberately instead of depending on launch location.
  • Specify text encodings and close resources with with.
  • Choose overwrite, append, or exclusive creation from the data policy.
TURN UNDERSTANDING INTO SOMETHING YOU CAN DO

Make it yours.

Type and test your code right here in the interactive workspace. Run your solution, check the output, and compare with the worked guide when ready.

01

Count meaningful lines

Write count_nonblank(path) that reads UTF-8 text one line at a time and counts lines containing something other than whitespace. Demonstrate it safely.

your_turn_1.py🐍Python
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.
Explore a worked solution
one_possible_solution.pyPython
from pathlib import Pathfrom tempfile import TemporaryDirectorydef count_nonblank(path):    with path.open(encoding="utf-8") as handle:        return sum(1 for line in handle if line.strip())with TemporaryDirectory() as folder:    path = Path(folder) / "notes.txt"    path.write_text("one\n \ntwo\n", encoding="utf-8")    assert count_nonblank(path) == 2

The generator consumes the file incrementally. strip() is appropriate here because whitespace-only lines are intentionally excluded.

02

Protect an existing export

Create a UTF-8 report only if its destination is unused. Verify that a second attempt raises FileExistsError and leaves the first content intact.

your_turn_2.py🐍Python
Ctrl + ↵
Output
Click Run or press Ctrl+Enter
Output will appear here after you run the code.
Explore a worked solution
one_possible_solution.pyPython
from pathlib import Pathfrom tempfile import TemporaryDirectorywith TemporaryDirectory() as folder:    path = Path(folder) / "report.txt"    with path.open("x", encoding="utf-8") as handle:        handle.write("first\n")    try:        with path.open("x", encoding="utf-8") as handle:            handle.write("second\n")    except FileExistsError:        pass    assert path.read_text(encoding="utf-8") == "first\n"

Exclusive creation enforces the policy during opening. Checking existence first would introduce a gap between the check and the write.

A SMALL QUESTION. A USEFUL NEXT STEP.

What stayed with you?

Check the ideas while they’re fresh. Your answers stay in this page and feedback appears as you go.

A LITTLE ACTIVE RECALL0 / 3 answered
01A script launched by a scheduler cannot find data.csv although it works in your editor. What should you investigate first?
02Which choice prevents an existing report from being replaced by this opening operation?
03Why might strip() be wrong when reading a fixed-width text file?
⚡CODING CHALLENGE
🔒Required to Mark Lesson Complete

Count meaningful lines

Write count_nonblank(path) that reads UTF-8 text one line at a time and counts lines containing something other than whitespace. Demonstrate it safely.

EXPECTED OUTPUT
[Process exited with code 0 - No output]
challenge.pyPython 3
Ctrl + ↵
Execution Console
Click "Run & Verify" (or press Ctrl + Enter) to test your code against the challenge.

Keep exploring.

The official references behind this chapter, when you want a second angle or the full details.

One chapter closer.

Reading is a start. Trying it yourself makes the connection.

Solve the hands-on coding challenge in the knowledge section to verify your code and unlock chapter completion.