Skip to content
  • Files & pathlib · Python

Files & pathlib

LearnViaNotes @learnvianotes· 4 min read

Reading and writing files safely with with, text vs binary modes, seeking and chunked reads, pathlib for paths, and shutil / tempfile for everything around them.

Text files

Python
import os, tempfile
path = os.path.join(tempfile.mkdtemp(), "notes.txt")

with open(path, "w", encoding="utf-8") as f:     # "w" truncates, "a" appends
    f.write("line one\nline two\n")

with open(path, encoding="utf-8") as f:           # default mode "r"
    for line in f:                                # streams line by line
        print(line.rstrip())
Output
line one
line two
ModeMeaning
'r'Read (default) — error if missing
'w'Write — creates or truncates
'a'Append to the end
'x'Create — error if it exists
'b'Binary, e.g. 'rb' for images
'+'Read and write

Reading methods

Python
import io
f = io.StringIO("alpha\nbeta\ngamma\n")    # behaves like an open text file

print(f.readline())            # alpha
print(f.read(3))               # bet
print(f.readlines())           # ['a\n', 'gamma\n']
print(repr(f.read()))          # ''   ← at the end, read() returns an empty string
Output
alpha

bet
['a\n', 'gamma\n']
''
CallReturnsMemory
for line in fOne line at a timeO(1) — best for big files
f.read()The whole file as one stringWhole file
f.read(n)Up to n characters (bytes in binary mode)O(n)
f.readline()Next line, including \nOne line
f.readlines()List of all linesWhole file
f.write(s) / f.writelines(lines)Write text (no newline added)—

Binary files, chunks & seek/tell

Python
import os, tempfile
path = os.path.join(tempfile.mkdtemp(), "data.bin")

with open(path, "wb") as f:
    f.write(bytes(range(10)))

chunks = []
with open(path, "rb") as f:
    while chunk := f.read(4):             # fixed-size chunks: constant memory
        chunks.append(chunk)
print(chunks)                             # [b'\x00\x01\x02\x03', b'\x04\x05\x06\x07', b'\x08\t']

with open(path, "rb") as f:
    f.seek(6)                             # jump to byte offset 6
    print(f.tell(), f.read(2))            # 6 b'\x06\x07'
    f.seek(-1, os.SEEK_END)               # 1 byte before the end
    print(f.read())                       # b'\t'

Temporary files & directories

Python
import os, tempfile

with tempfile.TemporaryDirectory() as d:          # deleted with everything inside
    path = os.path.join(d, "scratch.txt")
    with open(path, "w", encoding="utf-8") as f:
        f.write("draft")
    print(os.path.exists(path))                   # True
print(os.path.exists(d))                          # False

with tempfile.NamedTemporaryFile("w+", suffix=".txt", encoding="utf-8") as tmp:
    tmp.write("scratch")
    tmp.seek(0)                                   # rewind before reading back
    print(tmp.read(), tmp.name.endswith(".txt"))  # scratch True

pathlib

Python
from pathlib import Path
import tempfile

root = Path(tempfile.mkdtemp())
report = root / "reports" / "2026.txt"      # "/" joins paths
report.parent.mkdir(parents=True, exist_ok=True)
report.write_text("ok", encoding="utf-8")

print(report.name, report.stem, report.suffix)   # 2026.txt 2026 .txt
print(report.read_text(encoding="utf-8"))         # ok
print([p.name for p in root.rglob("*.txt")])      # ['2026.txt']
print(report.relative_to(root).as_posix())        # reports/2026.txt
print(report.with_suffix(".md").name)             # 2026.md
Taskos / os.pathpathlib
Joinos.path.join(a, b)Path(a) / b
File name / extensionos.path.basename(p), os.path.splitext(p)p.name, p.stem, p.suffix
Parent folderos.path.dirname(p)p.parent
Exists / is fileos.path.exists(p), os.path.isfile(p)p.exists(), p.is_file()
Make foldersos.makedirs(p, exist_ok=True)p.mkdir(parents=True, exist_ok=True)
List / pattern matchos.listdir(p), glob.glob('*.py')p.iterdir(), p.glob('*.py'), p.rglob('*.py')
Read whole fileopen(p).read()p.read_text(encoding=…), p.read_bytes()
Absolute pathos.path.abspath(p)p.resolve()

glob & shutil: finding, copying, moving

Python
import glob, os, shutil, tempfile
from pathlib import Path

with tempfile.TemporaryDirectory() as d:
    root = Path(d)
    for name in ["a.py", "b.py", "notes.md"]:
        (root / name).write_text(name, encoding="utf-8")

    print(sorted(p.name for p in root.glob("*.py")))                          # ['a.py', 'b.py']
    print(sorted(os.path.basename(p) for p in glob.glob(str(root / "*.md"))))  # ['notes.md']

    backup = root / "backup"
    backup.mkdir()
    shutil.copy(root / "a.py", backup)                  # copy into a folder
    shutil.move(root / "notes.md", backup / "README.md")  # move + rename
    print(sorted(p.name for p in backup.iterdir()))     # ['README.md', 'a.py']

    shutil.rmtree(backup)                               # delete a whole tree
    print(backup.exists())                              # False

Safe writes

Python
import os, tempfile
from pathlib import Path

def atomic_write(path: Path, text: str) -> None:
    """Readers see either the old file or the new one — never half a file."""
    tmp = path.with_suffix(path.suffix + ".tmp")
    tmp.write_text(text, encoding="utf-8")
    os.replace(tmp, path)            # atomic rename on the same filesystem

target = Path(tempfile.mkdtemp()) / "settings.json"
atomic_write(target, '{"theme": "dark"}')
print(target.read_text(encoding="utf-8"))   # {"theme": "dark"}

Structured formats — JSON, CSV, pickle, TOML — are covered in Serialization: JSON, CSV & pickle.

How would you process a 10 GB log file?

Free for students and teachers

Write notes like this one

Cards for every idea, quizzes and flashcards, read aloud — on the web and your phone.

Something wrong with this note? Open it to report