CSV
Python
Windows
carriage return
newline issue

CSV in Python adding an extra carriage return, on Windows

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

If Python CSV output on Windows appears to contain extra blank lines, the usual cause is newline handling between open() and the csv module. The fix is simple but important: when using csv.reader or csv.writer, open the file with newline='' so the csv module can manage line endings correctly.

Why the extra blank lines happen

The csv module writes row terminators itself. On Windows, text-mode file handling also performs newline translation unless told not to. If both layers try to handle line endings, you can end up with visibly doubled row spacing.

This incorrect pattern often triggers the problem:

python
1import csv
2
3with open("bad.csv", "w") as f:
4    writer = csv.writer(f)
5    writer.writerow(["id", "name"])
6    writer.writerow([1, "Alice"])

The code looks harmless, but on Windows it can produce an extra carriage-return effect when the file is opened in spreadsheet software or some editors.

The correct way to write CSV

Open the file with newline='' and usually specify an encoding explicitly as well.

python
1import csv
2
3with open("good.csv", "w", newline="", encoding="utf-8") as f:
4    writer = csv.writer(f)
5    writer.writerow(["id", "name"])
6    writer.writerow([1, "Alice"])
7    writer.writerow([2, "Bob"])

This is the standard cross-platform pattern recommended for Python CSV handling.

Reading CSV safely

The same newline='' pattern is also good practice when reading.

python
1import csv
2
3with open("good.csv", "r", newline="", encoding="utf-8") as f:
4    reader = csv.reader(f)
5    for row in reader:
6        print(row)

This keeps line handling under the control of the csv module rather than letting generic text translation interfere with parsing.

When you need explicit line terminators

Sometimes the integration target expects a specific row terminator. In that case, set lineterminator explicitly on the writer.

python
1import csv
2
3with open("custom.csv", "w", newline="", encoding="utf-8") as f:
4    writer = csv.writer(f, lineterminator="\n")
5    writer.writerow(["a", "b", "c"])

That is useful for systems that require exact formatting regardless of platform defaults.

Why this issue is especially famous on Windows

On Unix-like systems, the interaction is less surprising because newline handling is simpler. On Windows, the distinction between logical newlines and actual carriage-return/line-feed sequences is more visible, so mistakes show up as blank-looking rows.

That is why the exact same script can look correct during one developer's test and then appear broken when the file is opened elsewhere on a Windows machine.

That is why the same code may appear fine on one developer machine and broken on another.

A reusable helper pattern

If your project writes CSV often, wrap the opening and writing logic so the correct newline behavior is never forgotten.

python
1import csv
2
3
4def write_csv(path, rows):
5    with open(path, "w", newline="", encoding="utf-8") as f:
6        writer = csv.writer(f)
7        writer.writerows(rows)
8
9write_csv("data.csv", [["id", "name"], [1, "Alice"], [2, "Bob"]])

This reduces the chance of someone reintroducing the bug in a later script.

Common Pitfalls

A common mistake is opening CSV files with default text newline handling and assuming the csv module will compensate automatically.

This is one of those bugs that feels random until you realize the file-opening mode, not the row data, is what is broken.

Another mistake is treating the problem as an encoding issue when the real cause is newline translation.

A third mistake is testing only on one platform and not noticing that the CSV behavior changes on Windows.

Summary

  • Extra blank lines in Python CSV output on Windows usually come from newline handling.
  • Open CSV files with newline='' when using the csv module.
  • The same rule is a good practice for both reading and writing.
  • Set lineterminator explicitly when an integration requires exact row endings.
  • Treat this as a file-opening issue, not primarily an encoding issue.
  • Use newline="" consistently whenever the csv module owns line formatting.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions