write() and writelines()
Two methods put data into a text file, and both of them are far less helpful than print() has taught you to expect. They add no newline, no spaces and no commas — and they refuse a number outright.
1write() puts a string in the file
f.write(s) writes the string s into the file, starting wherever the pointer is. The file must be open in a mode that allows writing: 'w', 'a', or one of the + modes.
f = open('marks.txt', 'w')
f.write('Ravi')
f.write('Meera')
f.write('Amit')
f.close()
f = open('marks.txt', 'r')
print(f.read())
f.close()RaviMeeraAmit
print() ends every call with a newline, which is why two print()s give you two lines. write() ends with nothing. It writes precisely the characters you gave it, and the next write() carries straight on from there.So the newline is your job. Put \n at the end of every line you write:
f = open('marks.txt', 'w')
n = f.write('Ravi\n')
print(n)
f.write('Meera\n')
f.close()
f = open('marks.txt', 'r')
print(f.read())
f.close()5 Ravi Meera
5 is the answer from write(): the number of characters it wrote. 'Ravi\n' is five characters — four letters and the newline, which is one character, not two. You can ignore this answer, and almost every program does.2Strings only — numbers are refused
A text file holds characters, so write() takes a string and nothing else. Hand it a number and the program stops:
f = open('marks.txt', 'w')
f.write(95)
f.close()Traceback (most recent call last):
File "not_a_string.py", line 2, in <module>
f.write(95)
TypeError: write() argument must be str, not intThe fix is str(), or an f-string, both of which you have been using since Class 11:
marks = 95
f = open('marks.txt', 'w')
f.write(str(marks) + '\n')
f.write(f'Total: {marks}\n')
f.close()
f = open('marks.txt', 'r')
print(f.read())
f.close()95 Total: 95
3writelines() writes a whole list
f.writelines(lines) takes a list of strings and writes every one of them. The name is misleading: it does not put each item on its own line. It is exactly write() called once per item.
names = ['Ravi\n', 'Meera\n', 'Amit\n']
f = open('names.txt', 'w')
f.writelines(names)
f.close()
f = open('names.txt', 'r')
print(f.read())
f.close()Ravi Meera Amit
plain = ['Ravi', 'Meera', 'Amit']
f = open('glued.txt', 'w')
f.writelines(plain)
f.close()
f = open('glued.txt', 'r')
print(f.read())
f.close()RaviMeeraAmit
\n on the end of each item. writelines() adds no separator of any kind — not a newline, not a space, not a comma. If you want lines, the list must already contain them.And like write(), every item must be a string. f.writelines([1, 2, 3]) raises TypeError: write() argument must be str, not int — the same message, because that is what it is doing underneath.
4write() or writelines()?
| write() | writelines() | |
|---|---|---|
| Takes | one string | a list of strings |
| Adds a newline? | no | no |
| Gives back | the number of characters written | None |
| Non-string items | TypeError | TypeError |
| Use it when | you build the line yourself | the lines are already in a list |
These two programs write the same file. Neither is better; use whichever matches the data you are holding.
names = ['Ravi', 'Meera', 'Amit']
# one write() per name
with open('names.txt', 'w') as f:
for name in names:
f.write(name + '\n')
# or build the list first and write it in one call
lines = []
for name in names:
lines.append(name + '\n')
with open('names.txt', 'w') as f:
f.writelines(lines)
print(open('names.txt').read())Ravi Meera Amit
5Writing records: a name and a mark on each line
A text file has no columns and no fields — only lines. So a record is a line you build yourself, with a separator you choose. A comma is the usual one, and that is all a CSV file is.
Run it and the file holds three records:
Ravi,78
Meera,91
Amit,65| or a tab.6Adding, rather than replacing
Everything above opened the file in 'w', so every run started with an empty file. Change one letter and the same program adds to what is there:
'a' to 'w' above and run it again. Ravi, Meera and Amit are gone — one letter, three records.7Recap
Writes exactly that string at the pointer, and gives back how many characters it wrote.
Unlike print(). Three writes make one long line unless you put \n in yourself.
A number raises TypeError: write() argument must be str, not int. Wrap it in str() or use an f-string.
Writes every string in the list, one after another, adding nothing between them. Returns None.
Join the fields with a separator you choose, and end the line with \n.
'w' empties the file first; 'a' adds to the end. The writing code is identical.
- 1
Write the names of five subjects into
subjects.txt, one per line.Hint · A list, a for loop, and \n on the end of every write().
- 2
Do the same with one
writelines()call instead of a loop ofwrite().Hint · Build the list with the newlines already in it.
- 3
Ask the user for three names with
input()and append each one tonames.txt.Hint · Mode
'a', so a second run does not wipe the first. - 4
Write a name and a mark on each line, then print how many characters
write()reported for the longest one.Hint · write() gives the count back — put it in a variable.
f.write('Ravi'), f.write('Meera'), f.write('Amit'). What is in the file?
What does f.write('Hello\\n') give back?
marks = 95. Which line writes it into a text file?
f.writelines(['a', 'b', 'c']) — what does the file hold?