Reading & Writing Files

Python · Lesson 28 of 43 6 min read Updated

Everything stored in variables disappears when your program ends. To keep data, such as a list of students, a shop's daily sales or a game's high score, you save it in a file. Python makes reading and writing text files short and safe.

In this lesson you will open files with the with statement, pick the right mode, handle missing files, and work with paths and folders using the modern pathlib module. The examples run in the browser, where files live in a temporary folder that is cleared later.

Writing a file with open() and with

The built-in open() function opens a file and returns a file object that you read from or write to. Always open files inside a with block. When the block ends, Python closes the file for you, even if an error happens, so your data is saved properly.

PythonRun it yourself
with open("students.txt", "w", encoding="utf-8") as file:
    file.write("Aarav,Rohtak,82\n")
    file.write("Priya,Jaipur,91\n")
    file.write("Farhan,Lucknow,76\n")

print("File saved")
Output
File saved

open() takes three important arguments here:

  • The file name (or path): "students.txt".
  • The mode: "w" means write. It creates the file, or empties it if it already exists.
  • The encoding: "utf-8", the standard way to store text, which handles every language and symbol including Hindi and ₹.

write() does not add a new line by itself, so each string ends with \n.

File modes

ModeMeaningIf the file existsIf it does not exist
"r"Read (the default)Reads itFileNotFoundError
"w"WriteEmpties it firstCreates it
"a"AppendAdds to the endCreates it
"x"Create onlyFileExistsErrorCreates it

Add b for binary files such as images ("rb", "wb"). Binary files hold bytes, not text, so you do not pass an encoding for them.

Reading a file

You can read the whole file as one string with read(), or, more commonly, loop over the file object to get one line at a time. Looping is memory-friendly, because Python never holds the whole file at once.

PythonRun it yourself
with open("students.txt", "w", encoding="utf-8") as file:
    file.write("Aarav,Rohtak,82\nPriya,Jaipur,91\nFarhan,Lucknow,76\n")

with open("students.txt", encoding="utf-8") as file:
    print(repr(file.read()))

total = 0
with open("students.txt", encoding="utf-8") as file:
    for line in file:
        name, city, marks = line.strip().split(",")
        total += int(marks)
        print(f"{name:<8} {city:<8} {marks}")

print("Total marks:", total)
Output
'Aarav,Rohtak,82\nPriya,Jaipur,91\nFarhan,Lucknow,76\n'
Aarav    Rohtak   82
Priya    Jaipur   91
Farhan   Lucknow  76
Total marks: 249

Each line keeps its \n at the end, which is why the loop calls strip() before splitting. Everything read from a text file is a string, so int() converts the marks before adding them. Mode "r" is the default, so the read calls leave it out. For files with columns like this one, the csv module is even better; see JSON & CSV.

Appending and handling missing files

Mode "a" adds new text to the end without touching what is already there. It is perfect for logs. Reading a file that does not exist raises FileNotFoundError, which you can catch (see Errors & Exceptions).

PythonRun it yourself
for entry in ["09:00 Shop opened", "13:30 Lunch break", "21:00 Shop closed"]:
    with open("shop_log.txt", "a", encoding="utf-8") as log:
        print(entry, file=log)

with open("shop_log.txt", encoding="utf-8") as log:
    print(log.read(), end="")

try:
    with open("sales_2019.txt", encoding="utf-8") as old:
        print(old.read())
except FileNotFoundError:
    print("No file for 2019 yet")
Output
09:00 Shop opened
13:30 Lunch break
21:00 Shop closed
No file for 2019 yet

Notice print(entry, file=log): print() can write to a file, and it adds the newline for you.

Working with paths using pathlib

File names often come with folders, and folders are written differently on Windows (C:\Users\Isha) and Linux or macOS (/home/isha). The pathlib module handles these differences. A Path object represents a location, and the / operator joins parts together correctly on every system.

PythonRun it yourself
from pathlib import Path

reports = Path("reports") / "2026"
reports.mkdir(parents=True, exist_ok=True)

daily = reports / "sales-oct.txt"
daily.write_text("Chai: ₹1,840\nSamosa: ₹960\n", encoding="utf-8")

print(daily)
print(daily.name, daily.stem, daily.suffix)
print(daily.exists(), daily.parent)
print(daily.read_text(encoding="utf-8").splitlines())

for path in sorted(reports.glob("*.txt")):
    print("Found:", path.name)
Output
reports/2026/sales-oct.txt
sales-oct.txt sales-oct .txt
True reports/2026
['Chai: ₹1,840', 'Samosa: ₹960']
Found: sales-oct.txt

On Windows the paths print with backslashes, such as reports\2026\sales-oct.txt. Useful tools from this example:

  • mkdir(parents=True, exist_ok=True) creates the folder and any missing parent folders, and does not complain if they exist.
  • write_text() and read_text() open, write or read, and close the file in one call.
  • .name, .stem, .suffix and .parent split a path into its parts.
  • glob("*.txt") finds matching files in a folder.

Common mistakes

  • Opening with "w" by accident. Write mode erases the file immediately. Use "a" to add, and "x" when you must not overwrite.
  • Forgetting with. Without it, you must call file.close() yourself; if you forget or an error happens first, data may not be saved.
  • Leaving out the encoding. On Python 3.14 and older, Windows may use a different default. Always write encoding="utf-8" for text files.
  • Wrong working folder. A relative name such as "data.txt" is looked up in the folder your terminal is in, not the folder of your script. Build paths with Path(__file__).parent / "data.txt" when the file sits next to the script.
  • Backslashes in Windows paths. In "C:\new\test.txt", \n and \t become a newline and a tab. Use forward slashes, a raw string r"C:\new\test.txt", or Path.

Key points

  • Open files with with open(name, mode, encoding="utf-8") as f: so they are always closed.
  • Modes: "r" read, "w" write (erases), "a" append, "x" create only; add b for binary.
  • Loop over a file object to read it line by line, and strip() each line.
  • Data read from a text file is always a string; convert numbers yourself.
  • pathlib.Path joins paths with /, creates folders and reads or writes whole files with read_text() and write_text().
  • Python 3.15 makes UTF-8 the default, but an explicit encoding is still good practice.

Exercise

Write a program for a tuition centre in Kochi. Save these attendance lines to attendance.txt using pathlib: Meera,P, Rohan,A, Isha,P, Kabir,P, Ananya,A (P means present, A absent). Then read the file back line by line and print the names of absent students and the attendance percentage.

Show solution
Python
from pathlib import Path

path = Path("attendance.txt")
path.write_text("Meera,P\nRohan,A\nIsha,P\nKabir,P\nAnanya,A\n", encoding="utf-8")

present = 0
total = 0
with path.open(encoding="utf-8") as file:
    for line in file:
        name, status = line.strip().split(",")
        total += 1
        if status == "P":
            present += 1
        else:
            print("Absent:", name)

print(f"Attendance: {present / total:.0%}")
Output
Absent: Rohan
Absent: Ananya
Attendance: 60%

Path.open() works exactly like open() but starts from a Path object. The :.0% format turns 0.6 into 60%.

Quick Quiz

1. What happens when you open an existing file with mode "w"?

2. Why should you open files with a with block?

3. What type is every line you read from a text file?

4. What does Path("data") / "2026" / "sales.txt" create?

Learn Python with a mentor

Free lessons get you started. Our Python Programming training adds real projects and code reviews from working developers.

  • Project-based learning
  • Mentor code reviews
  • Free counselling call