writerows()
One letter longer than writerow(), and it does the loop for you. Hand it a list of rows and every one of them lands in the file. The whole lesson is that word of: a list of lists, not a list of values — and getting that wrong produces no error at all.
1writerows() — a whole table at once
w.writerows(a list of lists)Each inner list becomes one row. It is writerow() in a loop, written for you.
import csv
students = [[1, 'Ravi', 78], [2, 'Meera', 91], [3, 'Amit', 65]]
f = open('marks.csv', 'w', newline='')
w = csv.writer(f)
w.writerow(['Roll', 'Name', 'Marks'])
w.writerows(students)
f.close()
print(open('marks.csv', newline='').read())Roll,Name,Marks 1,Ravi,78 2,Meera,91 3,Amit,65
w.writerow(['Roll', 'Name', 'Marks'])One row, so writerow — singular. The header is a single list of three values.
w.writerows(students)Three rows, so writerows — plural. students is a list holding three lists, and each of those becomes a line.
no for loop anywhereThat is the whole gain. The three lines of loop from the previous lesson collapse into this one call.
2It is exactly the loop you would have written
These two halves produce the same file, byte for byte. Neither one is more correct — use whichever reads better:
for s in students:
w.writerow(s)Use this when each row needs checking or changing before it goes in.
w.writerows(students)
Use this when the list is already exactly what you want in the file.
3The trap: a list that is one level too shallow
writerows() expects each item to be a row, and a row is a list of values. Hand it a list of strings and it does not complain — it treats each string as a row, and each letter as a value:
import csv
f = open('trap.csv', 'w', newline='')
w = csv.writer(f)
w.writerows(['Ravi', 'Meera', 'Amit'])
f.close()
print(open('trap.csv', newline='').read())R,a,v,i M,e,e,r,a A,m,i,t
Numbers do not even get that far, because a number cannot be taken apart into values:
import csv
f = open('trap2.csv', 'w', newline='')
w = csv.writer(f)
w.writerows([1, 2, 3])
f.close()Traceback (most recent call last):
File "rows_trap2.py", line 5, in <module>
w.writerows([1, 2, 3])
_csv.Error: iterable expected, not int“Iterable” is Python's word for something you can loop over — a list, or a string. A number is not one, so this time it stops. What you almost certainly meant was three rows of one value each:
import csv
f = open('fixed.csv', 'w', newline='')
w = csv.writer(f)
w.writerows([[1], [2], [3]])
f.close()
print(open('fixed.csv', newline='').read())1 2 3
4Counting the brackets
The rule is easier to see than to say. Count the opening brackets:
w.writerow(['Ravi', 78])one [One row. writerow, singular.
w.writerows([['Ravi', 78], ['Meera', 91]])two [[Rows inside a list. writerows, plural.
w.writerows(['Ravi', 78])one [One bracket with writerows — the shapes do not match. 'Ravi' becomes R,a,v,i and 78 raises _csv.Error.
s on the end tells you there is one more layer of square brackets than you would otherwise need.5Try both, and break one on purpose
6The two, side by side
| writerow() | writerows() | |
|---|---|---|
| Takes | one list — a single row | a list of lists — many rows |
| Writes | one line | one line per inner list |
| Typical use | the header, or a row from input() | a table you already have in a variable |
| Gives back | the number of characters written | None |
| If you pass a plain string | one letter per column | one letter per column, on every row |
7Recap
Writes every row in one call. Nothing else is different — it is writerow() in a loop.
Each item must itself be a row. Two opening brackets where writerow had one.
R,a,v,i on its own line, one per string, and no error to warn you.
_csv.Error: iterable expected, not int — a number cannot be taken apart into values.
Unlike writerow(), which returns a character count. Neither is worth catching.
It is one row, written once, above the writerows() call.
- 1
Build a list of five rows in a variable and write the whole thing with one
writerows().Hint · A header with writerow() first, then the table.
- 2
Rewrite the same program with a
forloop andwriterow(), and compare the files.Hint · Identical. Pick whichever you find easier to read.
- 3
Pass
writerows()a flat list of names and look at the file.Hint · One letter per column, and Python said nothing.
- 4
Pass it a flat list of numbers and read the error carefully.
Hint · Iterable means “something you can loop over”.
What does writerows() expect as its argument?
w.writerows(['Ravi', 'Meera']) does what?
Why does w.writerows([1, 2, 3]) raise an error when the string version does not?
Which writes a header row followed by three records?