Reading from and Writing to Files#

Learning Objectives

Questions:

  • How can you read a file: all at once, line by line, or into a list?

  • How can you write data to a file: overwrite, append, or write multiple lines?

Objectives:

  • Open, read, and write text files in Python.

  • Understand why with open() is often preferable compared to open()/close().

  • Use the correct file mode ("r", "w", "a", "r+", "w+", "a+") for a given task.

  • Read file content in different ways and control the cursor position with seek().


Creating files to work with#

Before we begin, we need a few text files that we can use for practice later.
The code below will create these files for you.

At this stage, you do not need to understand how the code works - just run it once to generate the files.
Afterward, try opening the files and take a quick look at their content.

By the end of this lesson, you will be able to come back to this code and fully understand what it does.

# write to data.txt
with open("data.txt", "w", encoding="utf-8") as f:
    f.write("This is a small text file.\n")
    f.write("It has a few lines of content.\n")
    f.write("Each line ends with a newline character.\n")

# write to example.txt
with open("example.txt", "w", encoding="utf-8") as f:
    f.write("abcdefg\n")
    f.write("hijklmn\n")
    f.write("opqrstu\n")
    f.write("vwxyz")

# write to poem.txt
with open("poem.txt", "w", encoding="utf-8") as f:
    f.write("Roses are red\n")
    f.write("Violets are blue\n")
    f.write("Sugar is sweet\n")
    f.write("And so are you\n")
    f.write("\n")
    f.write("The end")

Reading from and writing to files in Python#

Working with files is one of the most common tasks in programming. Data is often stored in files, and your program may need to read from these files or write new information back.


Opening files#

The built-in function open() is used to open a file.

f = open("data.txt", "r")
content = f.read()
print(content)
f.close()
This is a small text file.
It has a few lines of content.
Each line ends with a newline character.
  • "r" means read mode.

  • .read() reads the file content as one string.

  • Important: When you use open() like this, you must remember to call .close(). If you forget, the file stays open in the background - and when writing, some data may remain in the buffer and never be saved properly, which can leave the file incomplete or corrupted.

Encoding#

When working with text files, it is good practice to always specify the file encoding.
By default, Python will use your operating system’s preferred encoding, which may differ across platforms (for example, UTF-8 on most Unix systems but CP-1252 on some Windows setups).

If you do not specify the encoding, text containing special characters (such as æ, ø, å) may not be read correctly, or you might get a UnicodeDecodeError.

The safest choice is to always write your file operations with an explicit encoding, most commonly UTF-8. UTF-8 is the standard text encoding on the web and on most modern systems, and it can represent all characters in the Unicode standard. By explicitly setting encoding="utf-8", you make sure that your code behaves consistently across different computers and operating systems - even if their defaults are different.

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

This way, you avoid problems such as:

  • Files containing special characters (æ, ø, å, or accented letters) not being read correctly.

  • Code working on your computer but failing with UnicodeDecodeError on someone else’s machine.

  • Subtle errors where characters are silently replaced or corrupted because the wrong encoding was assumed.

Using encoding="utf-8" is therefore considered best practice in modern Python programming.

File modes in open()#

When you use open(), the mode parameter tells Python how you want to use the file - for reading, writing, appending, or a combination. The table below shows the most common modes.

Mode

Meaning

Behavior

"r"

Read

File must exist.

"w"

Write

Creates a new file or truncates (empties) an existing one.

"a"

Append

Creates a new file if it doesn’t exist; otherwise writes at the end.

"r+"

Read and write

File must exist. Cursor starts at the beginning. Reading/writing works from current position. Does not truncate.

"w+"

Write and read

Creates a new file or truncates an existing one. Always starts with an empty file.

"a+"

Append and read

File is opened for reading, but all writes go to the end. Creates if missing.

"r+" vs. "w+" explained#

This is often confusing - here’s the difference.

Let us first look at the example.txt file:

with open("example.txt", "r", encoding="utf-8") as f:
    content = f.read()
    print(content)
abcdefg
hijklmn
opqrstu
vwxyz

If we use "r+":

# r+ → requires file to exist, does not truncate
with open("example.txt", "r+", encoding="utf-8") as f:
    f.write("HELLO")

Only the first characters are overwritten; the rest remains:

with open("example.txt", "r", encoding="utf-8") as f:
    content = f.read()
    print(content)
HELLOfg
hijklmn
opqrstu
vwxyz

If we instead use "w+":

# w+ → creates or truncates the file
with open("example.txt", "w+", encoding="utf-8") as f:
    f.write("HELLO")

Any previous content is gone:

with open("example.txt", "r", encoding="utf-8") as f:
    content = f.read()
    print(content)
HELLO

Reading examples#

Read entire file#

Reads the whole file into one string. Useful for small files, but not memory-efficient for very large ones.

with open("poem.txt", "r", encoding="utf-8") as f:
    content = f.read()
    print(content)
Roses are red
Violets are blue
Sugar is sweet
And so are you

The end

Read line by line#

Iterates through the file line by line. This is memory-friendly and often the best way when working with larger files.

with open("poem.txt", "r", encoding="utf-8") as f:
    for line in f:
        print(line.strip())
Roses are red
Violets are blue
Sugar is sweet
And so are you

The end

The strip() method removes any leading or trailing whitespace, such as the newline character \n at the end of each line.

Removing the newline is useful because otherwise print() will add its own line break, resulting in unwanted blank lines in the output.
This ensures the text looks clean and properly formatted when printed.

Read into a list#

Stores all lines in a list, where each element is one line (including \n). Convenient if you need random access to specific lines.

with open("poem.txt", "r", encoding="utf-8") as f:
    lines = f.readlines()
print(lines)
['Roses are red\n', 'Violets are blue\n', 'Sugar is sweet\n', 'And so are you\n', '\n', 'The end']

Writing examples#

Write (overwrite)#

Opens the file in "w" mode, which creates a new file or truncates (clears) the old one. Any existing content is lost.

with open("output.txt", "w", encoding="utf-8") as f:
    f.write("First line\n")
    f.write("Second line\n")

Append#

Opens the file in "a" mode, which keeps the old content and adds new lines at the end of the file.

with open("output.txt", "a", encoding="utf-8") as f:
    f.write("This is added at the end.\n")

Cursor and seek()#

  • The file has a cursor (position).

  • After f.read(), the cursor is at the end → a new f.read() returns an empty string.

  • Reset the cursor with f.seek(0).

with open("data.txt", "r", encoding="utf-8") as f:
    print(f.read())   # reads all
    f.seek(0)
    print(f.read())   # reads again
This is a small text file.
It has a few lines of content.
Each line ends with a newline character.

This is a small text file.
It has a few lines of content.
Each line ends with a newline character.

Changing the index value in seek() will change the starting position:

with open("data.txt", "r", encoding="utf-8") as f:
    f.seek(1)
    print(f.read())   # reads from index 1
his is a small text file.
It has a few lines of content.
Each line ends with a newline character.

Exercises#

Exercise 1: Read and print#

Open poem.txt, read the content and print it.

Do it first with open() + close(), then rewrite it using with open.

Exercise 2: Count lines#

Count how many lines are in poem.txt and print the result.

Exercise 3: Find a word#

Ask the user for a word and print which line numbers in poem.txt contain that word.

Hint: Use input() to ask the user which word to search for.

Exercise 4: Write a shopping list#

Ask the user for three shopping items and write them to shopping.txt.

Exercise 5: Append to note#

Ask the user for a short note and append it to notes.txt.


Key Points#

  • Use with open(..., encoding="utf-8") to handle files safely and consistently.

  • File modes ("r", "w", "a", plus +) control whether you read, write, or append - and if old content is kept or erased.

  • Files can be read all at once, line by line, or into a list, depending on your needs.

  • The file cursor moves as you read/write; use .seek() to change its position.