NANDHOO.

File I/O


Python makes reading and writing files straightforward. Whether you are saving user data, reading configuration files, processing log files, or working with CSVs and JSON, Python's file I/O tools handle it all.


Why This Chapter Matters


Files are how programs store data that persists beyond a single run. Logs, configs, exports, and imports all involve reading and writing files.


Opening a File


Use open() to open a file. The best practice is to use the with statement, which guarantees the file is closed automatically — even if an error occurs.


with open("notes.txt", "r") as file:
    content = file.read()
    print(content)

Without with, you must manually call file.close(), which is easy to forget.


File Modes


ModeMeaning
'r'Read (default) — error if file doesn't exist
'w'Write — creates or OVERWRITES the file
'a'Append — adds to end without overwriting
'x'Exclusive create — error if file already exists
'b'Binary mode (combine: 'rb', 'wb')
'+'Read and write (combine: 'r+', 'w+')

Writing to Files


Write (Overwrite)


with open("output.txt", "w") as file:
    file.write("Line 1\n")
    file.write("Line 2\n")

Append


with open("log.txt", "a") as file:
    file.write("New log entry\n")

Write Multiple Lines


lines = ["Asha\n", "Leo\n", "Mina\n"]

with open("names.txt", "w") as file: file.writelines(lines)


Reading from Files


Read Everything


with open("notes.txt", "r") as file:
    content = file.read()
    print(content)

Read Lines as a List


with open("notes.txt", "r") as file:
    lines = file.readlines()
    for line in lines:
        print(line.strip())   # .strip() removes the \n

Read One Line at a Time (Memory Efficient)


with open("large_file.txt", "r") as file:
    for line in file:   # iterate directly — best for large files
        print(line.strip())

Read a Single Line


with open("notes.txt", "r") as file:
    first_line = file.readline()

Working with File Paths


Use the pathlib module (recommended in modern Python) or os.path:


from pathlib import Path

Create a Path object

data_dir = Path("data") file_path = data_dir / "notes.txt"


Check existence

print(file_path.exists()) print(file_path.is_file()) print(file_path.is_dir())


Create directory

data_dir.mkdir(exist_ok=True)


List files in a directory

for file in Path(".").iterdir(): print(file.name)


Read and write with pathlib

text = file_path.read_text(encoding="utf-8") file_path.write_text("New content", encoding="utf-8")


Always specify encoding="utf-8" when working with text files for cross-platform safety.


Working with CSV Files


CSV (Comma-Separated Values) is a common format for tabular data.


Reading CSV


import csv

with open("students.csv", "r", newline="") as file: reader = csv.DictReader(file) for row in reader: print(row["name"], row["score"])


Writing CSV


import csv

students = [ {"name": "Asha", "score": 95}, {"name": "Leo", "score": 88} ]


with open("output.csv", "w", newline="") as file: writer = csv.DictWriter(file, fieldnames=["name", "score"]) writer.writeheader() writer.writerows(students)


Working with JSON Files


JSON is a standard format for configuration files and API data.


Reading JSON


import json

with open("config.json", "r") as file: config = json.load(file) # dict


print(config["database"]["host"])


Writing JSON


import json

data = { "name": "NANDHOO", "version": "1.0", "features": ["python", "javascript"] }


with open("config.json", "w") as file: json.dump(data, file, indent=4)


Convert Between JSON and String


import json

Dict to JSON string

json_string = json.dumps(data, indent=2) print(json_string)


JSON string to dict

parsed = json.loads(json_string)


Checking if a File Exists


from pathlib import Path

if Path("data.txt").exists(): print("File found") else: print("File not found")


Common Patterns


Safe File Read with Error Handling


from pathlib import Path

def read_file(filename): try: return Path(filename).read_text(encoding="utf-8") except FileNotFoundError: print(f"Error: '{filename}' not found.") return None except PermissionError: print(f"Error: No permission to read '{filename}'.") return None


Process Each Line


results = []
with open("data.txt", "r") as file:
    for line in file:
        value = line.strip()
        if value:   # skip empty lines
            results.append(value)

Common Mistakes


  • not using with (forgetting to close the file)
  • using 'w' mode when you meant 'a' (overwrites data!)
  • not stripping newlines from readlines() results
  • not specifying encoding, leading to cross-platform issues
  • reading a huge file entirely into memory instead of streaming line by line

Mini Exercises


  1. Write a program that saves a list of names to a file, one per line.
  2. Read the file back and count how many names it contains.
  3. Write a program that appends new entries to an existing log file.
  4. Read a JSON file into a Python dict and print all keys and values.
  5. Write a CSV with at least 3 columns and read it back with csv.DictReader.

Review Questions


  1. Why should you always use the with statement when opening files?
  2. What is the difference between 'w' and 'a' mode?
  3. Why is iterating over a file with for line in file: better than readlines() for large files?
  4. What does json.load() do vs json.loads()?
  5. Why should you specify encoding="utf-8" when opening text files?

Reference Checklist


  • I can read and write files using with open()
  • I know all common file modes and when to use each
  • I can process files line by line efficiently
  • I can read and write CSV files with the csv module
  • I can read and write JSON files with the json module
  • I can use pathlib.Path for cross-platform file paths