Files, File Types and Paths
Quick answer A file is storage that outlives your program; text files hold encoded characters, binary files hold raw machine bytes, CSV is a text file with a delimiter, and every path handed to open() is read either from the drive root (absolute) or from the current working folder (relative).
Every variable you have used so far lives in RAM. Close the program and it is gone. A school fee counter that forgets every receipt at shutdown is not software, it is a calculator. A file is a named area of storage on disk that survives after your program ends.
Python never touches the disk directly. You call open() and get back a file object (a file handle). Attached to it is a file pointer that remembers how far into the file you have gone. Every read and write moves that pointer. Most confusing output in this chapter is not a wrong function, it is a pointer sitting somewhere you did not expect.
The three file types the syllabus names
| Point | Text file | Binary file | CSV file |
|---|---|---|---|
| What is stored | Characters, turned into bytes by an encoding (UTF-8, cp1252) | The raw internal form of the data, byte for byte | Characters, exactly like a text file |
| Readable in Notepad | Yes | No, you see garbage | Yes |
| Line concept | Yes, lines end with \n | None, just a stream of bytes | Yes, one record per line |
| On reading | Everything is str, numbers need int() | Data returns in its original type | Everything is str |
| Extension | .txt .py .html | .dat .jpg .mp3 .exe | .csv |
| Opened with | open(f, "r") | open(f, "rb") | open(f, "r") plus the csv module |
Worked example: a text file stores characters, not numbers
Write 25000 into a text file, then peek at the bytes actually on disk by reopening in binary.
import os
f = open("fees.txt", "w")
f.write("25000")
f.close()
print("size on disk :", os.path.getsize("fees.txt"), "bytes")
f = open("fees.txt", "rb")
raw = f.read()
f.close()
print("raw bytes :", raw)
print("byte values :", list(raw))
f = open("fees.txt", "r")
data = f.read()
f.close()
print("read back :", repr(data), type(data))
print("data + '500' :", data + "500")
print("int(data)+500:", int(data) + 500)Real output:
size on disk : 5 bytes
raw bytes : b'25000'
byte values : [50, 53, 48, 48, 48]
read back : '25000'
data + '500' : 25000500
int(data)+500: 25500The byte values 50, 53, 48, 48, 48 are the ASCII codes of '2', '5', '0', '0', '0'. The number 25000 was never stored, only its printed form. That is why it returns as str and why data + "500" glues text instead of adding. Anything numeric from a text file must go through int() or float() first. Avoiding that constant encode-decode round trip is the whole reason binary files exist.
Worked example: CSV is a text file wearing a uniform
f = open("students.csv", "w")
f.write("rollno,name,marks\n")
f.write("1,Aarav,87\n")
f.write("2,Diya,91\n")
f.close()
f = open("students.csv", "r")
print(f.read())
f.close()Real output:
rollno,name,marks
1,Aarav,87
2,Diya,91Nothing special happened. read() returned ordinary text. The commas become columns only because some other program agrees to treat them that way, whether Excel or Python's csv module.
Absolute and relative paths
An absolute path starts at the root of the drive and is complete on its own, like C:\school\marks.txt or /home/aarav/marks.txt. A relative path is measured from the current working directory, the folder your program is running from, which is often not the folder your .py file sits in. That mismatch is why FileNotFoundError surprises people. Inside a relative path . means this folder and .. means one folder up. This ran from a folder called class12:
import os
print("Working folder :", os.getcwd())
print("marks.txt -> abs:", os.path.abspath("marks.txt"))
print("marks.txt -> isabs:", os.path.isabs("marks.txt"))
print("data/fees.txt -> abs:", os.path.abspath("data/fees.txt"))
print("../notes.txt -> abs:", os.path.abspath("../notes.txt"))
p = "X:\\data\\fees.txt"
print("isabs :", os.path.isabs(p))
print("dirname :", os.path.dirname(p))
print("basename :", os.path.basename(p))
print("join :", os.path.join("data", "fees.txt"))Real output:
Working folder : X:\class12
marks.txt -> abs: X:\class12\marks.txt
marks.txt -> isabs: False
data/fees.txt -> abs: X:\class12\data\fees.txt
../notes.txt -> abs: X:\notes.txt
isabs : True
dirname : X:\data
basename : fees.txt
join : data\fees.txtRead the third line carefully. "marks.txt" is relative, so isabs is False, and Python silently expanded it to X:\class12\marks.txt. Run the same script from another folder and those same nine characters point at a different file. Note also that abspath never checks whether the file exists; it is pure string arithmetic on the working folder.
The backslash trap, which costs marks every year
In a Python string \n is a newline and \t is a tab, and a Windows path is full of backslashes.
p1 = "C:\school\notes.txt"
print("careless repr :", repr(p1))
print(p1)
print("doubled repr :", repr("C:\\school\\notes.txt"))
print("raw repr :", repr(r"C:\school\notes.txt"))
print("forward repr :", repr("C:/school/notes.txt"))Real output, warning and all:
s1_backslash.py:1: SyntaxWarning: invalid escape sequence '\s'
p1 = "C:\school\notes.txt"
careless repr : 'C:\\school\notes.txt'
C:\school
otes.txt
doubled repr : 'C:\\school\\notes.txt'
raw repr : 'C:\\school\\notes.txt'
forward repr : 'C:/school/notes.txt'The \n in \notes.txt became a real newline, which is why the printed path broke across two lines. The three safe fixes are doubling the backslashes, prefixing the string with r, or using forward slashes, which Windows accepts perfectly well.
- A file object plus its file pointer is the whole model: open() gives the object, every read and write moves the pointer, close() releases it.
- A text file stores encoded characters, so 25000 occupies 5 bytes as '2','5','0','0','0' and returns as a str that must go through int() before arithmetic.
- A binary file stores the raw internal representation, has no line structure and is not human readable; a CSV file is only a text file with an agreed delimiter.
- An absolute path starts at the drive root and works from anywhere; a relative path is resolved against os.getcwd(), which need not be where your .py file sits.
- In Windows paths always double the backslashes, use a raw string, or use forward slashes, because \n and \t inside a normal string are escape sequences.
