Skip to lesson
Python for JS Developers

File I/O & DataLesson 1 of 2

File Operations

4 min

File handling in Python is built in and pleasantly synchronous. The with statement (a context manager) opens a file and guarantees it is closed when the block ends, even if an error occurs. No more forgetting to call close().

Pathlib is Python's modern path library. Instead of gluing strings together, you use the / operator: Path("data") / "file.txt". Paths are objects with useful methods and properties: .exists(), .read_text(), .write_text(), .suffix, .stem, .parent, and .glob().

Compared to Node's fs module, there is no callback-vs-promise-vs-sync decision to make. Reading a file is two lines: open it with with, then call .read(), or iterate over the file object to process it line by line.

Encoding needs your attention. open() does NOT default to UTF-8 everywhere: it uses the operating system's preferred encoding, which is UTF-8 on macOS and Linux but often cp1252 on Windows. Python 3.15 switches the default to UTF-8 on every platform (PEP 686), but until your code only runs on 3.15+, always pass encoding="utf-8" when you open text files. This prevents the classic "works on my Mac, crashes on Windows" UnicodeDecodeError.

Build paths with pathlib, not string concatenation. Python on Windows actually accepts forward slashes, so data + '/' + file.txt usually works, but string joining makes it easy to end up with doubled or missing separators, and you lose all the Path methods. Path("data") / "file.txt" (or os.path.join) is correct on every operating system.

Quick reference

JavaScriptPythonNote
fs.readFileSync('f', 'utf8')Path('f').read_text(encoding='utf-8')Pass the encoding explicitly
fs.writeFileSync('f', data)Path('f').write_text(data, encoding='utf-8')Or open('f', 'w')
fs.appendFileSync('f', data)open('f', 'a')Mode a appends
path.join(a, b)Path(a) / b/ operator on Path
path.extname('f.txt')Path('f.txt').suffix.suffix property
fs.existsSync('f')Path('f').exists()Path method
fs.globSync('*.py') (Node 22+)Path('.').glob('*.py')Built into pathlib

Side by side

JavaScript
// Node.js
const fs = require('fs');
const path = require('path');

const data = fs.readFileSync('file.txt', 'utf8');
fs.writeFileSync('out.txt', 'hello');
fs.existsSync('file.txt');

path.join(__dirname, 'data', 'file.txt');
path.extname('file.txt');
Python
# Python
# Read the whole file
with open("file.txt", encoding="utf-8") as f:
    data = f.read()

# Or iterate lines (memory efficient)
with open("file.txt", encoding="utf-8") as f:
    for line in f:
        print(line.strip())

# Write ("w" overwrites, "a" appends)
with open("out.txt", "w", encoding="utf-8") as f:
    f.write("hello")

# pathlib (modern paths)
from pathlib import Path
p = Path("data") / "subdir" / "file.txt"
p.exists()
p.suffix          # '.txt'
p.stem            # 'file'
p.parent          # Path('data/subdir')
p.read_text(encoding="utf-8")       # read shortcut
p.write_text("hi", encoding="utf-8")  # write shortcut

for f in Path(".").glob("*.py"):
    print(f)

Exercise

Real Python, running in your browser

Write Python code that:

A file named config.txt already exists in the current directory. 1. Use pathlib to create log_path = Path for "logs/app.log" (use the / operator) 2. Read "config.txt" with 'with open' (encoding="utf-8") and print each line stripped 3. Write "completed" to "status.txt" 4. Print every .txt file in the current directory using glob

Ctrl + Enter runCtrl + Shift + Enter checkTab indentEsc then Tab to leave the editorCtrl + / comment