This episode covers data input and output: file I/O with pathlib, processing CSV, JSON, and YAML, the security risks of pickle, and streaming data with generators and chunked processing to stay memory-efficient.

Real applications deal with data: reading files, sending JSON over APIs, and storing processing results. Episode 10 equips you with the I/O and serialization skills that form the backbone of almost every system.
We'll cover modern file I/O with pathlib, the CSV, JSON, and YAML data formats, the security risks of pickle, and streaming data with generators so you can process giant files without exhausting memory.
pathlib is the modern way to handle file paths, replacing os.path:
from pathlib import Path
folder = Path("data")
folder.mkdir(exist_ok=True)
file_baru = folder / "catatan.txt"
file_baru.write_text("Belajar Python itu menyenangkan\n")
print(file_baru)
print(file_baru.exists())Path("data") creates a path object, and the / operator joins paths cross-platform. write_text writes a file and exists() checks whether it's there. pathlib makes I/O code cleaner and easier to read.
CSV is the most common tabular format for data:
import csv
with open("produk.csv", "w", newline="") as f:
penulis = csv.writer(f)
penulis.writerow(["nama", "harga"])
penulis.writerow(["laptop", 15000000])
with open("produk.csv", "r") as f:
pembaca = csv.DictReader(f)
for baris in pembaca:
print(baris["nama"], baris["harga"])csv.DictReader(f) reads CSV and maps each row to a dict based on the header. csv.writer writes the data. CSV is simple and portable, good for exchanging data between systems.
JSON is the standard data exchange format on the web:
import json
data = {"nama": "Arman", "skill": ["Python", "Docker"]}
teks = json.dumps(data)
print(teks)
balik = json.loads(teks)
print(balik["nama"])
print(balik["skill"][0])json.dumps(data) converts a dict into a JSON string, and json.loads(teks) converts it back. For files, use json.dump and json.load. JSON is the common language between Python and other web services.
YAML is often used for configuration because it's easy to read. Use the pyyaml library:
pip install pyyamlimport yaml
konfigurasi = yaml.safe_load("""
server:
host: localhost
port: 8000
""")
print(konfigurasi["server"]["port"])yaml.safe_load parses YAML into Python objects. Always use safe_load — not load — because the unsafe version can execute malicious code. This is part of the security best practices we deepen in episode 14.
pickle can execute arbitrary code when loading data:
import pickle
data = {"nama": "Arman"}
blob = pickle.dumps(data)
print(pickle.loads(blob))pickle.dumps(data) and pickle.loads(blob) do work, but loading a pickle from an untrusted source is very dangerous — it can execute malicious code. The golden rule: never load a pickle from an untrusted source. For cross-system data, use JSON.
Generators process data lazily, one piece at a time:
def baca_berchunk(jalur, ukuran=1024):
with open(jalur, "rb") as f:
while True:
chunk = f.read(ukuran)
if not chunk:
break
yield chunk
for potongan in baca_berchunk("data/catatan.txt"):
print(len(potongan))yield chunk turns the function into a generator that produces data chunks one by one. A giant file is never loaded fully into memory — only the chunk currently being processed. This is a key pattern for large data pipelines.
Key takeaways:
In the next episode, episode 11, we'll cover configuration, secrets, and environment management — Twelve-Factor config via env vars, python-dotenv, dynaconf and pydantic settings, and best practices for managing secrets so they never get committed to Git. Your project is ready to be configured securely!