A Wandering Mind · Computer Science
PYTHON GUIDE

Learn · Run · Break · Fix

A learning series from A Wandering Mind

Eighteen interlinked lessons on strings, lists, files, exceptions, and dictionaries—with original explanations, runnable examples, real output, and supporting CPSC 1301K lectures.

course.py
>>> guide = {
...   "lessons": 18,
...   "modules": 5,
...   "python": "3.10+"
... }
>>> guide["goal"] = "understand it"
Module 3 · Files · Lesson 14 of 18

Writing and Appending to Files in Python

Reading brings data from a file into your program. Writing sends data in the opposite direction. Python’s write() method writes one string at a time, writelines() accepts an iterable of strings, write mode replaces existing file contents, and append mode preserves what is already there while adding new output at the end.

Prerequisite: Complete Reading Files and Processing Lines. All examples continue to use the safer with open(...) context-manager pattern from Lesson 12.

write() sends a string to an open file

The write() method accepts a string and sends those characters to a file that was opened with a mode permitting output. In the simplest case, open a file with "w", call write(), and allow the context manager to close the file when the block ends.

Unlike print(), write() does not automatically add a newline. If you want one line to end before the next begins, include \n yourself.

Example 1 · Write two linesVerified
with open("report.txt", "w", encoding="utf-8") as file:
    file.write("alpha\n")
    file.write("beta\n")

with open("report.txt", "r", encoding="utf-8") as file:
    print(file.read().strip())
alpha
beta

The second with block is only there to verify what was written. The first block performs the output. Both calls to write() receive strings, and each string includes its own newline.

write() does not behave like print(). It writes exactly the string you provide. No space separator and no trailing newline are added automatically.

Write mode replaces existing contents

The mode "w" is useful when the file should represent the program’s newest complete output. If the path does not exist, Python creates it. If it already exists, opening it in write mode truncates it immediately.

That means the destructive action happens at open(), not at the first call to write(). In verification, an existing file containing old data became zero bytes simply by opening it with "w" and then closing it without writing anything.

Use write mode when replacement is intentional. Do not casually test it against a file you need to preserve.

Append mode preserves old content

Append mode, "a", also allows writing and creates the file if it does not exist. The important difference is that output is placed at the end instead of replacing the previous contents.

Example 2 · Add a new line without replacing the old oneVerified
with open("log.txt", "w", encoding="utf-8") as file:
    file.write("first\n")

with open("log.txt", "a", encoding="utf-8") as file:
    file.write("second\n")

with open("log.txt", "r", encoding="utf-8") as file:
    print(file.read().strip())
first
second

The first block creates a starting file. The second opens the same path in append mode and adds another line after the existing text. This makes append mode appropriate for logs, histories, simple journals, and other outputs where old records should remain intact.

writelines() accepts multiple strings

The writelines() method accepts an iterable whose elements are strings. A list of strings is a common beginner example. Despite the method name, writelines() does not add line breaks for you. If each string should appear on its own line, the strings themselves must include \n.

Example 3 · Write a list of stringsVerified
lines = ["north\n", "south\n", "east\n"]
with open("directions.txt", "w", encoding="utf-8") as file:
    file.writelines(lines)

with open("directions.txt", "r", encoding="utf-8") as file:
    print(file.read().strip())
north
south
east

Because every element already ends with a newline, the file contains three visible lines. If the list were ["north", "south", "east"] instead, the resulting file would contain northsoutheast with no automatic separators.

A loop is often clearer than building newline strings first

When your program already has a list of values, you do not have to transform the whole collection before writing. A loop can format and write each value one at a time. This connects file output directly to the loop patterns from Module 2.

Example 4 · Write list items with a loopVerified
items = ["red", "green", "blue"]
with open("colors.txt", "w", encoding="utf-8") as file:
    for item in items:
        file.write(f"{item}\n")

with open("colors.txt", "r", encoding="utf-8") as file:
    print(file.read().strip())
red
green
blue

This pattern is especially useful when each value needs formatting, conversion, or additional text before it is written. The f-string produces a normal string, and write() sends that string to the file.

It also keeps the output rule close to the data transformation. If later you decide every line should include a label, timestamp, delimiter, or calculated value, you can change the single formatting expression inside the loop instead of rebuilding a separate list first. That makes loop-based writing a useful bridge between in-memory Python objects and a simple line-oriented text format.

Write one stringfile.write(text)

Writes exactly the supplied string; no newline is added automatically.

Write many stringsfile.writelines(strings)

Writes each string from an iterable without inventing separators.

Replace outputopen(path, "w")

Creates a new file or truncates an existing one.

Preserve and addopen(path, "a")

Creates the file if needed and writes at the end.

Text files still require strings

Text-mode file methods work with strings. If your program has an integer, float, or another non-string value, convert or format it before writing. An f-string is often the cleanest approach because it can combine labels, numbers, and newline characters in one expression.

For example, file.write(f"Score: {score}\n") works because the f-string evaluates to a string before write() receives it. Passing the integer directly does not.

Common mistakes while writing files

The four failures below were executed in Python. They show the two requirements that matter most: the file must be open in a mode that permits writing, and the values sent to text-mode write methods must be strings.

Mistake 1 · Writing to a read-only file
with open("report.txt", "r", encoding="utf-8") as file:
    file.write("hello")
Traceback (most recent call last):
  File "/tmp/ipykernel_313/4178984910.py", line 26, in run_err
    exec(compile(code, str(work / filename), "exec"), {})
    ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/tmp/awm_lesson14/mistake1_write_read_mode.py", line 2, in <module>
io.UnsupportedOperation: not writable

The path is open successfully, but "r" does not grant write access. Use a mode that matches the operation you intend.

Mistake 2 · Passing an integer directly to write()
with open("numbers.txt", "w", encoding="utf-8") as file:
    file.write(42)
Traceback (most recent call last):
  File "/tmp/ipykernel_313/4178984910.py", line 26, in run_err
    exec(compile(code, str(work / filename), "exec"), {})
    ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/tmp/awm_lesson14/mistake2_write_int.py", line 2, in <module>
TypeError: write() argument must be str, not int

Text-mode write() expects a string. Convert with str(42) or format the number inside an f-string.

Mistake 3 · Giving writelines() non-string elements
with open("lines.txt", "w", encoding="utf-8") as file:
    file.writelines([1, 2, 3])
Traceback (most recent call last):
  File "/tmp/ipykernel_313/4178984910.py", line 26, in run_err
    exec(compile(code, str(work / filename), "exec"), {})
    ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/tmp/awm_lesson14/mistake3_writelines_ints.py", line 2, in <module>
TypeError: write() argument must be str, not int

A list is a valid iterable, but its elements must still be strings. The container type alone does not make its contents writable as text.

Mistake 4 · Writing after the context manager has closed the file
with open("closed.txt", "w", encoding="utf-8") as file:
    pass
file.write("late")
Traceback (most recent call last):
  File "/tmp/ipykernel_313/4178984910.py", line 26, in run_err
    exec(compile(code, str(work / filename), "exec"), {})
    ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/tmp/awm_lesson14/mistake4_write_after_with.py", line 3, in <module>
ValueError: I/O operation on closed file.

The variable still refers to the file object after the block, but the context manager has closed its underlying resource. Keep the write operations inside the managed lifetime.

Supporting classroom explanation

This page is original A Wandering Mind instructional material. The assigned CPSC 1301K lecture below reinforces the core mechanics of sending text from a running program into a file.

Writing To a File — by Hyrum Carroll · 5:48. Watch on YouTube ↗ · CPSC 1301K playlist ↗

What it adds: a focused classroom walkthrough of opening a file for output and writing program data into it.

Try it yourself

Use disposable practice files while learning write mode. Predict the final file contents before opening the answer.

Exercise 1 · Write one message

Create message.txt, write Hello, Python! followed by a newline, then reopen the file and print the saved text.

Show one answer
with open("message.txt", "w", encoding="utf-8") as file:
    file.write("Hello, Python!\n")

with open("message.txt", "r", encoding="utf-8") as file:
    print(file.read().strip())
Hello, Python!

Exercise 2 · Append a second event

Create events.txt containing start, then reopen it in append mode and add finish. Print the final file contents.

Show one answer
with open("events.txt", "w", encoding="utf-8") as file:
    file.write("start\n")

with open("events.txt", "a", encoding="utf-8") as file:
    file.write("finish\n")

with open("events.txt", "r", encoding="utf-8") as file:
    print(file.read().strip())
start
finish

Exercise 3 · Write several names

Create a list containing "Ada\n", "Grace\n", and "Linus\n". Write the list with writelines(), then reopen and print the file.

Show one answer
names = ["Ada\n", "Grace\n", "Linus\n"]
with open("names.txt", "w", encoding="utf-8") as file:
    file.writelines(names)

with open("names.txt", "r", encoding="utf-8") as file:
    print(file.read().strip())
Ada
Grace
Linus

Module 3 complete: what comes next

You can now open, close, read, loop over, write, and append to text files using context managers. You also understand the major file modes and why write mode must be treated carefully. Those pieces are enough to build simple persistent programs that store information outside the current Python process.

Module 4 focuses on what happens when operations fail. Continue to Handling Exceptions in Python to learn how try, except, else, and finally let a program respond to predictable failures without immediately crashing.