Python Basics – Part 11: File Handling with open(), Modes, and Context Managers

Python Basics – Part 11: File Handling and Text Files

In this part of the Python Basics series, we focus on working with files in Python:
how to open, read, write, and append text files, how the file pointer works, and why the with statement is usually the safest and cleanest way to handle files.

Opening Files with open()

The built-in open() function is the entry point for file handling.
It returns a file object (more precisely, a TextIOWrapper for text mode).

Basic usage:

file1 = open('data.txt', 'w')
print(type(file1))   # <class '_io.TextIOWrapper'>
print(file1.mode)    # w

Notes:

  • The first argument is the file name or path (here ‘data.txt’).
  • The second argument is the mode: ‘w’ means write.
  • In mode ‘w’, the file is created if it does not exist.
  • If it exists, its contents are truncated (overwritten).

For real projects it is usually better to use an absolute or well-known path, and to be aware that a relative path is interpreted relative to the current working directory.

Writing to Files

Once you have a file object, you can use its methods to work with the file.

file1 = open('data.txt', 'w')
file1.write('Hello file!\n')
file1.write('Hello file again!\n')
file1.close()

Important:

  • Always close the file when you are done, so the data is flushed and the file handle is released.
  • You can write strings; if you want line breaks, you must include ‘\n’ yourself.

Reading from Files

The default mode of open() is ‘r’ (read), so you can omit it:

file2 = open('data.txt', 'r')
content = file2.read()
print(content)
file2.close()

read() returns the entire file as a single string, starting from the current file position (also called the file pointer).

If you try to open a non-existing file in read mode, you get a FileNotFoundError:

# file3 = open('i_do_not_exist.txt', 'r')  # FileNotFoundError

You can handle this with try/except if needed.

The File Pointer and seek()

When you call read(), the file pointer moves to the end of the file.
If you call read() again, you get an empty string.

file4 = open('data.txt', 'r')
print(file4.read())
print("Reading again:", file4.read())  # empty string

You can move the file pointer with seek():

file4.seek(0)      # go back to the beginning
print(file4.read())
file4.close()

seek(0) moves the pointer to the start of the file.
You can also use other positions (e.g. seek(10)), but for text files this is mainly useful when you know what you are doing.

File Modes: ‘w’, ‘a’, ‘r’, ‘w+’, ‘r+’, ‘a+’

Common text modes:

  • ‘r’ – read (file must exist)
  • ‘w’ – write (create or overwrite)
  • ‘a’ – append (write at the end; create if not exists)
  • ‘r+’ – read and write (file must exist, pointer at start)
  • ‘w+’ – read and write, but truncate file (like ‘w’)
  • ‘a+’ – read and append (pointer at end; can still read)

Example with append:

file5 = open('data.txt', 'a')
file5.write('Please append me!\n')
file5.close()

Example with ‘r+’ (read and write):

file6 = open('data.txt', 'r+')
for i in range(1, 5):
    file6.write(str(i) + '. Balloon\n')
file6.seek(0)
print(file6.read())
file6.close()

Note that opening with ‘r+’ requires the file to exist.
Opening with ‘w+’ will create or truncate the file before writing.

readline() and readlines()

Sometimes you want to read line by line instead of the whole file at once.

readline() returns the next line from the file:

file6 = open('data.txt', 'r')
print(file6.readline())  # first line
print(file6.readline())  # second line
print(file6.readline())  # third line
file6.close()

readlines() returns all remaining lines as a list of strings:

file6 = open('data.txt', 'r')
lines = file6.readlines()
print(lines)
file6.close()

For large files, it’s often better to iterate over the file object directly:

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

This reads the file lazily, one line at a time.

Using with for Safe File Handling

The with statement is the recommended way to work with files in Python.
It ensures that the file is automatically closed when the block is exited, even if an exception happens inside.

with open('data.txt', 'w+') as f:
    f.write('Hello')
    f.seek(0)
    print(f.read())  # Hello

Outside the with block, the file is already closed:

# f.seek(0)  # ValueError: I/O operation on closed file.

Advantages of using with:

  • No need to remember to call close()
  • Safer in case of errors
  • Cleaner and more readable code

Encoding and Text Files

By default, the encoding Python uses may depend on your system.
For portable code, it is a good idea to specify an encoding explicitly, often ‘utf-8’:

with open('data.txt', 'w', encoding='utf-8') as f:
    f.write("Hello, UTF-8 world! äöüß")

with open('data.txt', 'r', encoding='utf-8') as f:
    print(f.read())

This is especially important when working with non-ASCII characters.

Summary

In this part you learned how to:

  • Use open() with different modes to create, read, write, and append text files.
  • Work with the file pointer and seek().
  • Use read(), readline(), and readlines() to access file contents.
  • Safely handle files using the with statement so they are always closed properly.
  • Be aware of encoding when reading and writing text.

Leave a Reply

Your email address will not be published. Required fields are marked *