Home / Computer Science / Class XII / File Handling in Python
File Handling in Python — CUET Computer Science hero
Class XII 💻 Computer Science Ch 2 of 20

File Handling in Python

CUET unit: File Handling in Python

📌 Snapshot

  • Learn text and binary files, open modes, read and write methods, seek and tell, and pickle with traces.
  • Why variables vanish when a program ends, and how files on secondary storage keep your data safe.
  • Every access mode compared in one table, and the read, readline and readlines methods side by side.
  • Step by step traces of seek and tell, and of how pickle saves and reloads Python objects.

📖 Detailed Notes

Written and reviewed by Rohit Singh, Computer Science & Commerce faculty at UniDrill (MCA, Osmania University · 6 years teaching). Based on NCERT Computer Science Class XII, Chapter 2.

Where does your data go when the program ends?

Imagine a marks entry program. You type in 40 students' marks, close the program, and open it the next day. Everything is gone. Variables live in memory only while the program runs. To keep data for later, a program must store it in a file: a named location on secondary storage (hard disk, pen drive, SSD) where data stays permanently.

This chapter follows the life of a file in Python: open it, read or write it, move around in it, and close it. Then it adds one powerful trick, the pickle module, which stores whole Python objects such as lists and records.

Text files and binary files

Every file stores bytes, but what the bytes mean differs.

Feature Text file Binary file
Stores A sequence of characters: letters, digits and symbols Raw bytes (0s and 1s) that stand for images, audio, video, compressed files, programs
Examples .txt, .py, .csv .jpg, .mp3, .exe, .dat
Encoding Characters saved as bytes using ASCII, Unicode or another scheme The bytes mean whatever the program that made them says
Line ending Each line ends with an End of Line (EOL) character, \n in Python No lines
In a text editor Readable Garbage values
Damage A changed character affects only that character Even a single changed bit can make the file unreadable
Mode letter Default Add b, as in rb or wb

Why binary files break so easily. A binary file has a precise structure that its own software expects. A JPEG image, for instance, is a carefully ordered stream of bytes. Change one bit in the wrong place and the software can no longer decode it. Text has no hidden structure to break, which is why you can read a damaged text file in any editor.

Beyond the textbook. For the exam: in a text file each line ends with the single EOL character \n. In reality: Windows stores line endings as two characters, but Python quietly converts them to \n when it reads a text file and converts back when it writes. Your code sees the same \n on every system.

Opening a file

The built in function open() links your program to a file:

file_object = open(file_name, access_mode)

It returns a file handle, stored in file_object, which you use for every later operation. The second argument is optional: if you leave it out, the file opens in read mode (r) as a text file. The file object carries three useful attributes.

Attribute Gives
file_object.closed True if the file is closed
file_object.mode The access mode used
file_object.name The file name

The access mode decides what you may do and where the offset (the current position) starts. This table is the most tested one in the chapter.

Mode You can Offset starts File missing Existing data
r Read only Beginning Error Kept
rb Read only, binary Beginning Error Kept
r+ Read and write Beginning Error Kept (writing overwrites from the offset)
w Write only Beginning File is created Erased
wb+ Read and write, binary Beginning File is created Erased
a Append (write at the end) End File is created Kept
a+ Append and read End File is created Kept

Two quick rules cover the whole table. Modes that start with r never create a file, so they need it to exist. Modes with w always erase, so a careless open(name, "w") on an existing file destroys its contents. Binary versions simply add b, and wb and ab are the modes used with pickle.

Worked example: what is in the file? The file a.txt is opened and closed three times in a row. What does it contain at the end?

Step Statements Mode File content afterwards
1 Write Hi w Hi
2 Write Bye a HiBye
3 Write X w X (opening in w erased everything)

The wrong step is to read the third w as "write more". Write mode starts from nothing every time.

Closing a file, and the with clause

file_object.close() pushes any unsaved data to the file and frees the memory used. This matters because write() first puts data in a buffer (a holding area in memory). The data reaches permanent storage only when the file is closed, or when you call flush() to force it out. A program that crashes before closing can lose data still sitting in the buffer.

The with clause removes the risk:

Code
with open("notes.txt", "r") as f:
    data = f.read()
print(f.closed)
Output
True

The file is closed automatically when control leaves the with block, even if an exception occurs inside it. No explicit close() is needed, which is why modern code prefers with. It does the job of a try with a finally that closes the file.

Writing to a text file

Method Argument Returns Adds a newline?
write(s) One string The number of characters written No
writelines(seq) A list or tuple of strings Nothing (None) No

Both methods need strings. To write a number, convert it first with str(), otherwise Python raises TypeError. Neither method adds \n for you, so you put line breaks in yourself.

Worked example: write and writelines. What does this program print, and what ends up in the file?

Code
f = open("a.txt", "w")
print(f.write("Hi\n"))
f.writelines(["ab", "cd", "ef"])
f.write(str(25))
f.close()
Output
3

write("Hi\n") returns 3, counting H, i and the newline. The next two calls add no line breaks, so everything joins up.

Line of a.txt Content
1 Hi
2 abcdef25

Reading from a text file

Suppose poem.txt holds three lines, with no newline after the last one:

Line Text Characters (with newline)
1 Hello everyone 15
2 Writing multiline strings 26
3 This is the third line 22
Call Returns Type
read() The whole file, 'Hello everyone\nWriting multiline strings\nThis is the third line' One string
read(5) The next 5 bytes, 'Hello' (for plain English text, 5 characters) String
readline() One line including its newline, 'Hello everyone\n' String
readlines() ['Hello everyone\n', 'Writing multiline strings\n', 'This is the third line'] List of strings
read().splitlines() ['Hello everyone', 'Writing multiline strings', 'This is the third line'] List without newlines

Notice that readlines() keeps the \n at the end of each line, while splitlines() removes them. The last line has no \n only because the file does not end with one. When the end of the file is reached, readline() returns an empty string '', not None. That empty string is how a loop knows to stop.

Code
f = open("poem.txt", "r")
line = f.readline()
while line:
    print(line, end="")
    line = f.readline()
f.close()

The loop is true while line holds text. An empty string counts as false, so the loop ends at the end of the file.

Pause and predict: after two readline() calls on poem.txt, what does read(4) return?

Check your answer: 'This'. Each readline() moves the offset past its line, so after two calls the offset is at the start of line 3, and read(4) takes the first four characters of it.

tell() and seek(): moving inside a file

A file object remembers its offset, the number of bytes from the beginning where the next read or write will happen. tell() reports it. seek(offset, reference_point) moves it. The reference point is optional and defaults to 0.

reference_point Offset is counted from
0 (default) The beginning of the file
1 The current position
2 The end of the file

Worked example: tracing the offset. Using poem.txt from above:

Statement Result tell() afterwards
f = open("poem.txt") File opens in read mode 0
f.read(5) 'Hello' 5
f.readline() ' everyone\n' (the rest of line 1) 15
f.readline() 'Writing multiline strings\n' 41
f.seek(0) Back to the start 0
f.seek(10) Moves to byte 10 10
f.read(4) 'yone' 14
f.read() The remaining 49 characters 63
f.readline() '' (end of file) 63

Everything is counted in bytes, never in lines. tell() after reading line 1 is 15, not 1. This is why reading a file twice needs seek(0) in between: after the first full read the offset sits at the end.

Beyond the textbook. For the exam: seek(offset, reference_point) accepts 0, 1 and 2 as reference points. In reality: a file opened in text mode only allows seek(offset, 0) freely. Moving by a non zero offset from the current position or from the end raises an error, and only binary files accept all three reference points. For the same reason, the offsets you pass to seek() in text mode should come from earlier tell() calls or be 0.

Writing and then reading the same file

Mode w+ creates (or erases) a file and lets you both write and read. After writing, the offset is at the end, so seek(0) is needed before reading back.

Code
f = open("marks.txt", "w+")
f.write("Asha 85\n")
f.write("Ravi 72\n")
f.seek(0)
print(f.read())
f.close()
Output
Asha 85
Ravi 72

A short program can then total the marks. Each line is split into words with split(), and the second word is converted to a number.

Code
total = 0
with open("marks.txt") as f:
    for line in f:
        parts = line.split()
        total = total + int(parts[1])
print(total)
Output
157

Pause and predict: a file data.txt contains Hello. It is opened with open("data.txt", "a+"), and the very next statement is print(f.read()). What is printed?

Check your answer: An empty line. Mode a+ starts the offset at the end of the file, so read() finds nothing to read. A seek(0) first would let it read Hello.

The pickle module: saving whole objects

A text file can only hold text, so a record such as [101, "Asha", 95] would come back as a string, not as a list. Python's pickle module solves this. Pickling (serialisation) turns a Python object into a stream of bytes that can be stored in a binary file or sent over a network. Unpickling (de-serialisation) turns the bytes back into the original object, with the same structure and data types.

The steps never change. Import pickle, open the file in binary mode, call dump() or load(), then close it.

Function Syntax File mode needed What it does
dump() pickle.dump(data_object, file_object) wb (new) or ab (add to the end) Pickles one object into the file
load() store_object = pickle.load(file_object) rb Unpickles the next object from the file
Code
import pickle
records = [[101, "Asha", 95], [102, "Ravi", 88]]
f = open("emp.dat", "wb")
for rec in records:
    pickle.dump(rec, f)
f.close()
f = open("emp.dat", "rb")
try:
    while True:
        print(pickle.load(f))
except EOFError:
    pass
f.close()
Output
[101, 'Asha', 95]
[102, 'Ravi', 88]

Each dump() writes one object, so several records need a loop. Each load() reads the next one in the same order. When the objects run out, load() raises EOFError. This is exactly why the reading loop sits inside a try with except EOFError: the error is the signal for "no more records", which links this chapter directly to Exception Handling.

Worked example: how many records? The program above runs three times. How many records does emp.dat hold after each run, if the open mode changes as shown?

Run Mode used Records dumped Records in file afterwards
1 wb 3 3
2 ab 2 5 (appended after the old ones)
3 wb 1 1 (the old records are erased)

Beyond the textbook. For the exam: pickle stores any Python object in a binary file. In reality: never unpickle a file that came from someone you do not trust. Loading a pickle can run code hidden inside it, so pickle is meant only for data your own programs wrote. For data you exchange with other people or systems, formats such as CSV are the safer choice.

Exam traps

Trap Why it tempts Truth
open(name, "w") adds to the file "Write" sounds like "add" w erases existing content; a adds
The default mode of open() is w Writing is the more active mode The default is r, text
writelines() puts each item on its own line The name suggests lines It adds no newlines, so items join up
readline() returns None at the end Many functions return None for nothing It returns an empty string ''
tell() returns the line number We think in lines It returns the byte offset
The default reference_point of seek() is 1 Current position feels natural The default is 0, the beginning
pickle.dump() works on a file opened with w Writing is writing It needs binary mode wb or ab; a text mode file raises TypeError
write() accepts a number Print accepts numbers It needs a string, so use str(25)

60-second revision

Idea Remember
File Named location on secondary storage; keeps data after the program ends
Text vs binary Text has characters and EOL \n; binary has raw bytes and mode letter b
open() open(file_name, access_mode) returns a file handle; default is r text
Modes r, rb, r+ start at the beginning; w, wb+ erase; a, a+ start at the end
close and with close() flushes the buffer; with closes automatically, even on error
Writing write() takes a string and returns the character count; writelines() takes a sequence and returns None
Reading read() is everything, readline() is one line, readlines() is a list of lines
End of file readline() and read() give ''
tell and seek tell() gives the byte offset; seek(offset, 0 or 1 or 2) moves it
pickle dump() with wb or ab; load() with rb; EOFError ends the loop

Where this chapter connects

The finally clause and the with statement are two ways to guarantee a file closes, so revisit Exception Handling in Python. Later chapters read data back from files too, for example in Data Handling using Pandas I.

🎯 Practice MCQs

First 3 questions free · create a free account to unlock the rest — answers & explanations included, no payment needed

Q1. Which call opens the file data.txt for both reading and writing, with the file offset at the beginning?

▸ Show answer & explanation

Answer: B

Mode r+ allows reading and writing from the beginning. Mode a+ also reads and writes, but its offset starts at the end. Mode rb is read only, and mode w is write only and erases the file.

Q2. Which statement about the write() method of a text file is correct?

▸ Show answer & explanation

Answer: C

write() works through a buffer, so closing the file (or calling flush) is what saves the data. It returns the number of characters written, not None, and it accepts only strings, so an integer must first be converted with str().

Q3. A file myfile.txt has three lines: Hello everyone, Writing multiline strings and This is the third line, with no newline after the last line. What does print(f.readlines()) show for a file opened in r mode?

▸ Show answer & explanation

Answer: C

readlines() returns a list, and every element keeps its trailing newline except the last, because the file does not end with one. Option B shows what splitlines() would give. Options A and D have the wrong data type.

🔒 12 more practice MCQs

Create a free account to unlock every MCQ in this chapter — answers and explanations included. No payment needed.

Already registered? Just log in and they'll all appear here.

📊 Previous-Year Questions

Practise with real CUET Computer Science previous-year papers — every question solved, with the correct answer and a step-by-step explanation.

View solved CUET PYQ papers →

Ready to drill Computer Science?

Unlock all MCQs, chapter tests, mocks & PYQs for ₹199/year.

Get UniDrill Pro