Skip to content
Hello Python
6/7

File Handling

Topic 6 of 7, with 3 concept checks. Reading, writing, and working with files safely

Treat files as resources with explicit lifetimes

Resource ownership

Choose text or binary mode deliberately, keep encoding and cursor position visible, and guarantee closure even when reading, parsing, or writing raises an exception.

Core lesson 01

with open(...) as f: guarantees f.close() runs even if the code inside raises, unlike manual open()/close() where an exception before close() leaks the file handle.

A file object is a context manager — __enter__ returns the file itself, __exit__ closes it. Using with means you never have to remember to call .close(), and critically, the file still gets closed if something goes wrong while reading or writing, which a plain f = open(...); ...; f.close() sequence does not guarantee.

Python example
with open("notes.txt", "w", encoding="utf-8") as f:
    f.write("line 1\n")
    f.write("line 2\n")
# file is guaranteed closed here, even if write() had raised

with open("notes.txt", encoding="utf-8") as f:
    content = f.read()
print(content)

What to remember

Why should you use with open(...) as f: instead of manually calling open()/close()?

Common footguns

  • Forgetting that opening in 'w' mode truncates (erases) an existing file immediately — use 'a' to append instead.

Core lesson 02

Text mode ('r'/'w', the default) reads/writes str and handles encoding plus newline translation automatically. Binary mode ('rb'/'wb') reads/writes raw bytes with no decoding or translation.

Text mode decodes bytes from disk into str using an encoding (best made explicit with encoding="utf-8") and translates line endings. Binary mode gives you the raw bytes exactly as stored, with none of that — necessary for non-text files (images, archives) or when you need exact byte-for-byte control.

Python example
with open("data.bin", "wb") as f:
    f.write(b"\x00\x01\x02")

with open("data.bin", "rb") as f:
    raw = f.read()
print(raw)               # b'\x00\x01\x02'
print(type(raw))         # <class 'bytes'>

with open("notes.txt", "w", encoding="utf-8") as f:
    f.write("cafe au lait")     # str, encoded to utf-8 bytes on write

What to remember

What's the difference between text mode and binary mode when opening files?

Common footguns

  • Opening a binary file (image, zip) in text mode — decoding likely raises UnicodeDecodeError or silently corrupts the data.
  • Omitting encoding= on open() and getting different results on different machines — always pass encoding="utf-8" explicitly for text files.

Core lesson 03

Iterate the file object directly with a for loop — it yields one line at a time lazily, so memory use stays constant regardless of file size, unlike f.read() or f.readlines().

f.read() loads the entire file into a single string; f.readlines() loads it into a list of lines — both use memory proportional to file size. A file object is itself an iterator over its lines, so for line in f: reads and yields one line at a time, discarding it once processed, using O(1) memory regardless of whether the file is a few lines or a few gigabytes.

Python example
with open("huge_log.txt", encoding="utf-8") as f:
    for line in f:
        if "ERROR" in line:
            print(line.strip())
# never holds the whole file in memory at once

What to remember

How do you read a large file line-by-line without loading it all into memory?

Common footguns

  • Calling f.readlines() 'just to be safe' on a file that might be huge — defeats the whole point and can exhaust memory.

Python lab

Browser Python lab

Runtime · idle

Python loads on your first run. Your code stays in this browser.

Best practices

  • Always specify encoding="utf-8" explicitly when opening text files.
  • Always use with open(...) rather than manual open/close.
  • Iterate large files line-by-line instead of reading them fully into memory.
  • Use pathlib.Path instead of raw string paths for new code.

Apply the concept in Interview practice

Read N Characters Given Read4easyLeetCode #157 · O(n) time

Repeatedly call the given read4(buf) API to fill a 4-character internal buffer, copying out only as many characters as still needed into the destination buffer.

Open problem
Read N Characters Given Read4 II - Call Multiple TimeshardLeetCode #158 · O(n) time across all calls

Keep leftover characters from a previous read4() call in a persistent buffer between invocations, since a prior call may have read more than was consumed.

Open problem

Concept checks

Q01

Why should you use with open(...) as f: instead of manually calling open()/close()?

Q02

What's the difference between text mode and binary mode when opening files?

Q03

How do you read a large file line-by-line without loading it all into memory?