Of course! In Python, "filestream" is a common way to refer to the process of reading from or writing to a file. This is handled using built-in functions and objects, primarily the open() function and the resulting file object.

Here's a comprehensive guide covering everything from the basics to more advanced topics.
The Basics: open() and with Statement
The core of file handling in Python is the open() function. It returns a file object, which acts as a stream to the file on your disk.
The with Statement (Best Practice)
You should always use the with statement when working with files. It automatically handles closing the file for you, even if errors occur. This prevents resource leaks and data corruption.
# The recommended way to open a file
with open('my_file.txt', 'w') as f:
# 'f' is the file object (our stream)
f.write('Hello, world!')
# No need to call f.close() - the 'with' block does it automatically.
Opening Modes
The second argument to open() is the mode, which specifies how you intend to use the file.

| Mode | Description |
|---|---|
'r' |
Read (default). Opens the file for reading. Fails if the file doesn't exist. |
'w' |
Write. Opens the file for writing. Creates the file if it doesn't exist. Overwrites the file if it does exist. |
'a' |
Append. Opens the file for writing. Creates the file if it doesn't exist. Adds to the end of the file if it does exist. |
'x' |
Exclusive creation. Opens the file for writing. Fails if the file already exists. |
'r+' |
Read and Write. Starts at the beginning of the file. |
'a+' |
Read and Append. Starts at the end of the file for writing, but allows reading from anywhere. |
'b' |
Binary. Use this for non-text files (e.g., images, PDFs). Can be combined with other modes (e.g., 'rb', 'wb', 'ab'). |
't' |
Text (default). This is the default mode, so you don't need to specify it. |
Reading from a File
Let's assume you have a file named hello.txt with the following content:
Line 1: This is the first line.
Line 2: This is the second line.
Line 3: This is the third line.
Method 1: read() - Reads the entire file
This method reads the whole file into a single string.
with open('hello.txt', 'r') as f:
content = f.read()
print(content)
# Output:
# Line 1: This is the first line.
# Line 2: This is the second line.
# Line 3: This is the third line.
Method 2: readline() - Reads one line at a time
This method reads a single line from the file, including the newline character (\n).
with open('hello.txt', 'r') as f:
line1 = f.readline()
print(f"First line: {line1.strip()}") # .strip() removes leading/trailing whitespace
line2 = f.readline()
print(f"Second line: {line2.strip()}")
# Output:
# First line: Line 1: This is the first line.
# Second line: Line 2: This is the second line.
Method 3: readlines() - Reads all lines into a list
This method reads all lines from the file and returns them as a list of strings.

with open('hello.txt', 'r') as f:
lines = f.readlines()
print(lines)
# Output:
# ['Line 1: This is the first line.\n', 'Line 2: This is the second line.\n', 'Line 3: This is the third line.\n']
for line in lines:
print(line.strip())
Method 4: The Best Practice - Iterating Directly
The most Pythonic and memory-efficient way to read a file line by line is to loop over the file object directly. This avoids loading the entire file into memory.
with open('hello.txt', 'r') as f:
for line in f:
# The 'line' variable will contain each line, including the newline character
print(line.strip())
Writing to a File
Method 1: write() - Writes a string
This method writes a string to the file. Important: If the file already exists, this will overwrite it.
with open('new_file.txt', 'w') as f:
f.write('This is the first line.\n')
f.write('This is the second line.\n')
Method 2: writelines() - Writes a list of strings
This method takes a list of strings and writes them to the file. It does not add newlines (\n) automatically.
lines_to_write = [
'First line from writelines.\n',
'Second line from writelines.\n'
]
with open('new_file.txt', 'w') as f:
f.writelines(lines_to_write)
Appending to a File
To add content to the end of an existing file, use the 'a' (append) mode.
# Assuming 'new_file.txt' already exists from the previous example
with open('new_file.txt', 'a') as f:
f.write('This line is appended to the end.\n')
Handling Binary Files (e.g., Images, PDFs)
For non-text files, you must open them in binary mode ('rb', 'wb', 'ab'). When you read, you get bytes objects, and when you write, you must provide bytes objects.
Let's say you have an image named my_image.png.
Reading a Binary File
# We use a try/except block because the file might not exist
try:
with open('my_image.png', 'rb') as f:
image_data = f.read()
# image_data is now a bytes object
print(f"Read {len(image_data)} bytes from the image.")
except FileNotFoundError:
print("Error: The image file was not found.")
Writing a Binary File
# Create some dummy binary data
data_to_write = b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR...' # 'b' prefix makes it a bytes object
with open('my_image_copy.png', 'wb') as f:
f.write(data_to_write)
Advanced: File Object Attributes and Methods
The file object (f) has several useful attributes and methods:
| Attribute/Method | Description |
|---|---|
f.closed |
True if the file is closed, False otherwise. |
f.mode |
The mode the file was opened with (e.g., 'r', 'wb'). |
f.name |
The name of the file. |
f.tell() |
Returns the current file pointer's position (in bytes for binary files, or characters for text files). |
f.seek(offset, whence=0) |
Moves the file pointer. whence=0 (default) is from the start, whence=1 is from the current position, whence=2 is from the end. |
Example: seek() and tell()
with open('hello.txt', 'r') as f:
print(f"Initial position: {f.tell()}") # 0
f.read(5) # Reads "Line "
print(f"Position after reading 5 chars: {f.tell()}") # 5
f.seek(0) # Go back to the beginning of the file
print(f"Position after seeking to 0: {f.tell()}") # 0
first_line = f.readline()
print(f"First line: {first_line.strip()}")
print(f"Position after readline: {f.tell()}") # Position at the end of the first line
Common Pitfalls and Best Practices
-
Always use
with: It's the safest way to ensure your file is closed. -
Specify Encoding: For text files, it's crucial to specify an encoding (usually
utf-8) to avoidUnicodeDecodeError.# Best practice for text files with open('my_file.txt', 'r', encoding='utf-8') as f: ... -
Handle
FileNotFoundError: Wrap your file operations in atry...exceptblock if the file might not exist. -
Don't Forget Newlines: When writing text with
write(), remember to add\nto the end of each line if you want them on separate lines. Theprint()function does this for you automatically.# Good with open('log.txt', 'a') as f: f.write(f"An event occurred at {time.strftime('%Y-%m-%d %H:%M:%S')}\n") # Also Good (and often more convenient) with open('log.txt', 'a') as f: print(f"An event occurred at {time.strftime('%Y-%m-%d %H:%M:%S')}", file=f)
