How to Read Text Files in Python
Learn how to open, read, iterate through, and safely close text files in Python with practical examples.
What You Need Before Starting
This lesson assumes you know Python variables, strings, function calls, methods, for loops, and how to create or write a simple text file. You should also understand that a relative file path is interpreted from the program's current working directory.
Suppose new_file.txt contains:
Hello from Python.
Reading files is useful.Opening a Text File for Reading
Python's open() function opens a file and returns a file object. A file object provides methods and iteration for working with the file's contents.
Pass the filename as the first argument and the opening mode as the second argument:
fr = open("new_file.txt", "r")The "r" mode means read mode. It opens an existing file so that Python can read its contents. Read mode does not create a missing file. If Python cannot find the file, it normally raises FileNotFoundError.
| Mode | Meaning | Requires existing file | Can modify file |
|---|---|---|---|
r | Read an existing file | Yes | No |
w | Write a file; usually replaces existing contents | No | Yes |
a | Append data to the end of a file | No; Python can create it | Yes |
This lesson focuses on r. The other modes are included as a reminder that opening mode determines what operations are allowed.
File paths
If the file is not in the current working directory, provide a relative or absolute path. For example:
fr = open("data/new_file.txt", "r")For text files whose encoding is known, specifying it explicitly makes the program more predictable:
fr = open("new_file.txt", "r", encoding="utf-8")Reading the Entire File with read()
The file object's read() method returns all remaining file contents as one string. Assign that string to a variable and display it with print():
fr = open("new_file.txt", "r")
text = fr.read()
print(text)
fr.close()For a small file, this is a straightforward approach. The complete text is stored in the text variable.
The file cursor
A file cursor is the current position in a file. Reading starts at the cursor and advances it. After read() consumes the remaining content, the cursor is at the end of the file.
fr = open("new_file.txt", "r")
first_read = fr.read()
second_read = fr.read()
print(first_read)
print(repr(second_read)) # ''
fr.close()The second call returns an empty string because there is no unread content left. To read the contents again, reopen the file or move the cursor back to the beginning with fr.seek(0):
fr.seek(0)
again = fr.read()Closing an Explicitly Opened File
Calling open() uses a file resource. When all reading is complete, call the file object's close() method to release that resource:
fr = open("new_file.txt", "r")
text = fr.read()
print(text)
fr.close()Close the file only after all operations that need it are complete. After closing, do not try to read from or iterate over that file object.
Reading One Line at a Time
A file object is iterable, which means a loop can obtain values from it one at a time. Iterating over a text file produces one line per loop iteration.
fr = open("new_file.txt", "r")
line_number = 1
for line in fr:
print(line_number, "line:", line, end="")
line_number += 1
fr.close()Here, line_number labels each line. The counter increases after each iteration.
Why use end=""?
Lines read from a text file commonly retain their trailing newline character, represented as \n. The print() function normally adds another newline. Without end="", those two newline characters can produce an extra blank line between outputs.
Another option is to remove surrounding whitespace before printing:
with open("new_file.txt", "r") as fr:
for line_number, line in enumerate(fr, start=1):
print(line_number, "line:", line.rstrip())rstrip() removes trailing whitespace, including the line-ending character. Use it when removing that whitespace is appropriate for your output.
Choosing a Reading Approach
| Approach | Result | Best use | Memory consideration |
|---|---|---|---|
read() | One string containing all remaining content | Small files or situations where all text is needed at once | Loads the remaining content into memory |
for line in file_object | One line per iteration | Incremental processing, filtering, counting, or inspecting large files | Generally more memory-friendly because it does not load the whole file at once |
readline() | The next single line as a string | When code needs explicit control over individual reads | Typically memory-friendly; repeated calls advance the cursor |
Choose read() when the file is small or your operation needs the complete text. Choose line-by-line iteration when processing can happen incrementally, especially for larger files.
All these methods advance the file cursor. If content has already been consumed, reopen the file or reposition the cursor with seek(0) before rereading it.
Preferred File Handling with with
The preferred modern pattern is a with statement:
with open("new_file.txt", "r") as fr:
text = fr.read()
print(text)The with statement uses a context manager. A context manager manages setup and cleanup around a block of code. When execution leaves the block, Python closes the file automatically, including when an error occurs inside the block.
Whole-file reading with automatic cleanup
with open("new_file.txt", "r", encoding="utf-8") as fr:
text = fr.read()
print(text)The variable text remains available after the block, but the file object fr has been closed.
Line-by-line reading with automatic cleanup
with open("new_file.txt", "r", encoding="utf-8") as fr:
for line_number, line in enumerate(fr, start=1):
if line.strip():
print(line_number, line.strip())enumerate() supplies both a counter and the current line. start=1 makes the first line number 1. The condition ignores empty or whitespace-only lines, while strip() removes surrounding whitespace for display.
Troubleshooting File Reading
FileNotFoundError
This exception means Python could not locate the requested file. Check for:
- A misspelled filename or extension.
- A file stored in a different folder.
- A relative path based on an unexpected current working directory.
Confirm the file's location and provide the correct relative or absolute path. You can also review file locations with operating-system tools or Python's path utilities.
A second read() returns ""
The first call probably moved the file cursor to the end. Save the first result, reopen the file, or call seek(0) before reading again.
Extra blank lines appear
The input line may already contain \n, and print() adds another newline. Use print(line, end="") or remove the trailing line ending with line.rstrip().
The file remains open after an error
Manual close() may not run if an exception interrupts execution. Replace the explicit open-and-close pattern with with open(...) as fr:.
Unreadable characters or decoding errors
The file may use an encoding different from the platform default. If the file's encoding is known, specify it:
with open("new_file.txt", "r", encoding="utf-8") as fr:
text = fr.read()Complete Examples
Display all text from a small file
with open("new_file.txt", "r") as fr:
text = fr.read()
print(text)This stores the entire file in one string and prints it.
Label every line
with open("new_file.txt", "r") as fr:
line_number = 1
for line in fr:
print(line_number, "line:", line, end="")
line_number += 1This processes one line per iteration and avoids doubled blank lines.
Inspect non-empty lines in a larger file
with open("new_file.txt", "r") as fr:
for line_number, line in enumerate(fr, start=1):
if line.strip():
print(line_number, line.strip())This approach processes lines incrementally rather than loading the entire file into one string.
Key Points to Remember
open(filename, "r")returns a file object for reading an existing file.- Read mode does not create a missing file; an invalid path commonly raises
FileNotFoundError. read()returns all remaining content as one string and moves the cursor to the end.- A file object can be used in a
forloop to process one line at a time. - Read lines often include a trailing newline character.
- Use
with open(...)so Python closes the file automatically. - Reopen a file or use
seek(0)before rereading consumed content.
For related fundamentals, review Python strings, the for loop, and reading and writing files.