Use csv.DictWriter. Tell it the column names once, write the header, then hand it your rows as dictionaries.
import csv orders = [ {"id": "A-1001", "customer": "Ada", "total": 49.99}, {"id": "A-1002", "customer": "Grace", "total": 120.00}, ] with open("orders.csv", "w", newline="", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=["id", "customer", "total"]) writer.writeheader() writer.writerows(orders) with open("orders.csv", encoding="utf-8") as f: print(f.read())
id,customer,total A-1001,Ada,49.99 A-1002,Grace,120.0
Notice 120.0: the writer calls str() on each value. If the file is going to a person, format it yourself first, for example f"{total:.2f}".
Don't build the line with string joins
",".join(values) works right up until a value contains a comma. The csv module quotes it for you, which is the whole reason to use it.
import csv, io with io.StringIO() as out: # stands in for an open file writer = csv.writer(out) writer.writerow(["Hopper, Grace", 'She said "hi"', 120]) print(out.getvalue())
"Hopper, Grace","She said ""hi""",120
Any spreadsheet program reads that back as three cells, exactly as written.
The two things that bite
- A blank line between every row on Windows: you forgot
newline=""inopen(). The writer already ends each row with\r\n; withoutnewline="", Windows adds another. - Excel shows
ZoëasZoë: Excel assumes the old Windows encoding. Write withencoding="utf-8-sig"and Excel recognises the file as UTF-8.
To add rows to a file that already exists, open it with "a" instead of "w" and skip writeheader().