8. Files, JSON & errors¶
Beginner · 9 min read
Loading documents, saving results and surviving bad input — the everyday plumbing of every project.
8.1 Reading and writing text files¶
from pathlib import Path
path = Path("notes.txt")
path.write_text("RAG = retrieval + generation\n", encoding="utf-8") # create / overwrite
text = path.read_text(encoding="utf-8") # read it all back
print(text.strip()) # → RAG = retrieval + generation
# The `with` block closes the file for you, even if an error happens.
with open(path, "a", encoding="utf-8") as f: # "a" = append, "w" = overwrite, "r" = read
f.write("Agents = LLM + tools\n")
with open(path, encoding="utf-8") as f:
for line in f: # read line by line (memory-friendly for big files)
print(line.strip())
Always pass encoding="utf-8" — Windows otherwise uses a different default and breaks on ₹, emoji or Hindi text.
8.2 Working with folders¶
from pathlib import Path
docs = Path("docs")
docs.mkdir(exist_ok=True) # create the folder if missing
(docs / "a.md").write_text("hello", encoding="utf-8") # "/" joins paths on any OS
for file in sorted(docs.glob("*.md")): # every .md file in the folder
print(file.name, file.stat().st_size, "bytes") # → a.md 5 bytes
8.3 JSON¶
import json
config = {"model": "gpt-4o-mini", "temperature": 0.2, "tags": ["rag", "demo"]}
text = json.dumps(config) # Python dict → JSON string
print(text)
# → {"model": "gpt-4o-mini", "temperature": 0.2, "tags": ["rag", "demo"]}
back = json.loads(text) # JSON string → Python dict
print(back["tags"][0]) # → rag
with open("config.json", "w", encoding="utf-8") as f:
json.dump(config, f, indent=2) # write to a file, nicely indented
with open("config.json", encoding="utf-8") as f:
print(json.load(f)["model"]) # → gpt-4o-mini
8.4 Handling errors: try / except¶
def parse_score(raw):
try:
return float(raw) # code that might fail
except ValueError: # catch the specific error you expect
print(f"Not a number: {raw!r}")
return 0.0
print(parse_score("0.75")) # → 0.75
print(parse_score("high")) # prints a warning, then → 0.0
try:
data = json.loads('{"broken": ') # invalid JSON
except json.JSONDecodeError as err: # `as err` gives you the error object
print("Bad JSON at position", err.pos) # → Bad JSON at position 11
else:
print("parsed fine") # runs only if there was NO error
finally:
print("done") # always runs — cleanup goes here
Catch specific exceptions. A bare except: hides real bugs.
8.5 Raising your own errors¶
def chunk(text, size):
if size <= 0:
raise ValueError("size must be positive") # stop with a clear message
words = text.split()
return [" ".join(words[i:i + size]) for i in range(0, len(words), size)]
print(chunk("a b c d e", 2)) # → ['a b', 'c d', 'e']
Why it matters for GenAI
Models are asked to return JSON constantly — and sometimes they return invalid JSON. Parsing
inside try/except json.JSONDecodeError and retrying is a standard pattern.
Practice¶
- Save a list of three chat messages to
history.json, read it back and print the last message's content. - Write
safe_int(text, default=0)that returnsdefaultwhen the text isn't a number.