VMware ESXi and vSphere Cluster Management

Read and Write Files in Python with the with Statement

Learn how to safely read, write, append, and update text files in Python with open(), file modes, encoding, seek(), and automatic cleanup.

Python must open a file before your program can read its contents or change them. The built-in open() function opens the file and returns a file object, which provides methods such as read(), write(), and seek().

The with statement manages the file for the duration of an indented block. When execution leaves that block, Python closes the file automatically—even if an error interrupts the block. This makes file handling safer than relying on a manual close() call.

Basic with open() Syntax

The general pattern is:

with open('filename.txt', 'mode', encoding='utf-8') as file:
    # read or write using file
  • open() is the built-in function that opens a file.
  • 'filename.txt' identifies the file. It can be a relative path or a full path.
  • 'mode' specifies what your program may do with the file.
  • encoding='utf-8' specifies how text is decoded when reading and encoded when writing.
  • as file assigns the returned file object to the variable named file.
  • The indented statements are the operations performed while the file is open.

The variable after as is an ordinary variable name. You could call it source, output_file, or another descriptive name; it represents the open file object inside the block.

Why Use with?

Without a with statement, you would need to close the file yourself:

file = open('notes.txt', 'r', encoding='utf-8')
try:
    text = file.read()
finally:
    file.close()

A manual close() call can work, but it is easier to forget or skip when an exception occurs. With a context manager, the setup and cleanup are tied to the block:

with open('notes.txt', 'r', encoding='utf-8') as file:
    text = file.read()

A context manager is an object or operation that handles setup and cleanup around a block of code. open() can be used as a context manager in a with statement.

Reading an Entire Text File

Use read mode, r, to read an existing file. Read mode is also the default, so the mode can be omitted, although writing it explicitly often makes the code clearer.

with open('new_file.txt', 'r', encoding='utf-8') as file:
    text = file.read()

print(text)

read() returns the remaining file content as one string. In this example, the string is stored in text and printed after the with block. The file has already been closed when print(text) runs, but the string remains available.

Every file object has a file cursor: the current position used for reading or writing. read() starts at the current cursor position and consumes the remaining content. A second call may return an empty string if the cursor is already at the end.

Writing Text to a File

Use w mode to write replacement content:

with open('new_file.txt', 'w', encoding='utf-8') as file:
    file.write('Hello, world!\n')

write() writes a string. It does not automatically add a newline, so include \n when separate lines are needed. The example writes one line ending with a newline character.

Values passed to write() must be strings. Convert other values before writing:

count = 42

with open('count.txt', 'w', encoding='utf-8') as file:
    file.write(str(count))

Python Text File Modes

The file mode determines whether a file must already exist, whether reading and writing are permitted, and what happens to existing data.

ModeCan readCan writeFile must existEffect on existing contentTypical use
rYesNoYesPreservedRead an existing file
wNoYesNoTruncated and replacedCreate or completely rewrite a file
aNoYesNoPreserved; new data goes to the endAdd entries or lines
r+YesYesYesPreservedRead and update an existing file

Choose the mode deliberately. Using w when you intended to add information can cause accidental data loss. Use a when the goal is to preserve existing content and add new content at the end.

Appending Without Overwriting

Append mode adds new text to the end of a file:

with open('new_file.txt', 'a', encoding='utf-8') as file:
    file.write('Another message\n')

If new_file.txt already contains text, that text remains. If the file does not exist, append mode creates it. Include a newline when each appended value should appear on its own line.

Reading and Updating with r+

r+ opens an existing file for both reading and writing. It does not inherently append. Writing occurs at the current file cursor position.

with open('new_file.txt', 'r+', encoding='utf-8') as file:
    current_text = file.read()
    file.seek(0)
    file.write('Updated: ' + current_text)

After read(), the cursor is at the end of the file. seek(0) moves it back to the beginning, so the next write() starts at position zero. This example writes new text over the beginning of the file; if the new content is shorter than the old content, leftover characters can remain. For a complete replacement, w is usually clearer.

Use seek() when a read/write workflow requires a specific position:

with open('data.txt', 'r+', encoding='utf-8') as file:
    first_part = file.read(5)
    file.seek(0)
    file.write('Start')

File Operation Methods

MethodPurposeReturn value or behaviorImportant note
read()Read text from the current cursor positionReturns a stringConsumes the remaining content unless a size is supplied
write(text)Write text at the current cursor positionReturns the number of characters writtenThe argument must be a string; it does not add newlines
seek(position)Move the file cursorChanges the current positionUseful when combining reading and writing
close()Close the file objectCloses access to the fileNormally unnecessary inside a with statement

Paths and Text Encoding

A relative filename such as 'notes.txt' is interpreted relative to the program's current working directory, usually the directory from which the program was started. A full path identifies a location more explicitly, but the path must be valid for the operating system.

Specify an encoding for predictable text handling:

with open('notes.txt', 'r', encoding='utf-8') as file:
    notes = file.read()

Encoding is the character representation used to decode bytes into text when reading and to encode text when writing. UTF-8 is a common choice for modern text files. If a file was created with another encoding, use that file's actual encoding.

For larger programs, pathlib provides platform-safe path construction:

from pathlib import Path

path = Path('data') / 'notes.txt'
with path.open('r', encoding='utf-8') as file:
    text = file.read()

Handling Common File Errors

File operations can fail because a path is wrong, access is restricted, or the file's encoding does not match the selected encoding. Handle only errors you can respond to meaningfully.

Missing Files

try:
    with open('notes.txt', 'r', encoding='utf-8') as file:
        print(file.read())
except FileNotFoundError:
    print('The notes file does not exist yet.')

r and r+ raise FileNotFoundError when the target does not exist. Check the filename, spelling, and current working directory. Create the file first, or use w or a when creation is intended.

Permission Failures

PermissionError means the program cannot access the file or directory, or the operating system protects the target. Use a writable location, check permissions, and verify that the target is not restricted.

Encoding Failures

UnicodeDecodeError can occur when the selected encoding cannot decode the file's contents. Specify the encoding that was actually used to create the file; UTF-8 is commonly correct but is not universal.

Writing a Non-String

Passing an integer, list, or other non-string value to write() raises TypeError. Convert it with str() or format it into a string first.

score = 95
with open('score.txt', 'w', encoding='utf-8') as file:
    file.write(f'Score: {score}\n')

Troubleshooting File Operations

SymptomLikely causeResolution
FileNotFoundError while readingThe path is incorrect or the file has not been createdCheck the working directory and spelling, use the correct path, or create the file intentionally
Previous text disappearedThe file was opened with wUse a to add at the end, or use a deliberate read/modify/write workflow
Lines appear joinedwrite() was used without newline charactersAdd \n where each line should end
Nothing is written after reading with r+read() moved the cursor to the endCall seek(0) or seek to the intended write position
TypeError from write()A non-string value was passedUse str() or a formatted string
UnicodeDecodeError or incorrect charactersThe encoding does not match the fileSpecify the correct encoding
PermissionErrorThe location or file is not accessibleCheck permissions and use a writable location

Exam-Relevant Notes

  • with open(...) as file: creates a managed file context and closes the file when the block ends.
  • r reads an existing file, w writes while truncating existing content, a appends, and r+ reads and writes an existing file.
  • read() returns a string and advances the file cursor.
  • write() accepts a string and does not add \n automatically.
  • r+ does not mean append; use seek() to control the write location.
  • Adding encoding='utf-8' makes text handling explicit and predictable when the file uses UTF-8.

Summary

Use with open(...) whenever you work with a text file. Select r to read, w to replace, a to append, and r+ for controlled reading and writing of an existing file. Specify an appropriate encoding, remember that write() needs explicit newline characters, and use seek() when a read/write workflow needs a particular cursor position.

Continue with Python file reading and writing with the with statement.