πŸ”„ Quick Recap (Day 14)

  • You protected class data with encapsulation and properties.

  • You created and applied a custom decorator to log method calls.

🎯 What You’ll Learn Today

  1. Why reading from and writing to files is essential.

  2. How to open, write to, and close files safely.

  3. Using context managers (with statement) for automatic cleanup.

  4. Handling errors gracefully with try, except, and finally.

πŸ“– Why File I/O Matters

Computers need a way to persist information across runsβ€”like saving high scores, logs, or user data. File I/O lets your program:

  • Save results so you can re-open them later.

  • Share data between different parts of your code or programs.

  • Log events and errors for debugging and auditing.

Without file I/O, your program’s data would vanish when it stops running.

πŸ“– Opening and Writing Files

To write data:

  1. Open a file in write mode ('w'):

    file = open('data.txt', 'w')
  2. Write text using write() or writelines():

    file.write('Hello, world!\n')
    file.writelines(['Line 2\n', 'Line 3\n'])
  3. Close the file to flush data to disk:

    file.close()

If you open in 'w' mode, the file is created or truncated (emptied) if it exists.

πŸ“– Reading Files Safely

To read data back:

  • Open in read mode ('r'):

    file = open('data.txt', 'r')
  • Read entire content or line by line:

    content = file.read()             # all text
    lines = file.readlines()          # list of lines
  • Close afterward:

    file.close()

Reading line by line in a loop:

with open('data.txt', 'r') as f:
    for line in f:
        print(line.strip())

This prints each line without extra blank lines.

πŸ“– Using Context Managers

The with statement automates closing:

with open('data.txt', 'w') as f:
    f.write('Hello, with!\n')
# f is closed automatically here

Context managers prevent resource leaks and errors from forgetting close().

πŸ“– Handling Exceptions

File operations can fail (missing file, no permissions) sometimes. Use try/except:

try:
    with open('missing.txt', 'r') as f:
        data = f.read()
except FileNotFoundError:
    print('Error: missing file.')
except IOError:
    print('Error: cannot read file.')
finally:
    print('Finished file attempt.')
  • except catches specific errors and prevents crashes.

  • finally always runs (cleanup or final message).

πŸ§™β€β™‚οΈ Take the Wand and Try Yourself

  1. Create a file file_io.py.

  2. Write a function save_list(filename, items) that:

    • Opens filename for writing.

    • Writes each item from items list on its own line.

    • Closes the file.

  3. Write a function load_list(filename) that:

    • Tries to open filename for reading.

    • Reads lines into a list (stripping whitespace).

    • Returns the list, or an empty list if the file is missing.

  4. In if __name__=='__main__'::

    • Call save_list('names.txt', ['Alice', 'Bob', 'Charlie']).

    • Call load_list('names.txt') and print the returned list.

Solution Example (file_io.py):

# file_io.py

def save_list(filename, items):
    with open(filename, 'w') as f:
        for item in items:
            f.write(item + '\n')


def load_list(filename):
    try:
        with open(filename, 'r') as f:
            return [line.strip() for line in f]
    except FileNotFoundError:
        return []


if __name__ == '__main__':
    save_list('names.txt', ['Alice', 'Bob', 'Charlie'])
    names = load_list('names.txt')
    print(names)

Expected output:

['Alice', 'Bob', 'Charlie']

Run:

python file_io.py

Once you see the list printed and no errors occur, you’ve mastered file I/O and exception handling!

Up next: Day 16: Working with Packages & Virtual Envs


Keep Reading