369
import csv

with open('test.csv', 'w') as outfile:
    writer = csv.writer(outfile, delimiter=',', quoting=csv.QUOTE_MINIMAL)
    writer.writerow(['hi', 'dude'])
    writer.writerow(['hi2', 'dude2'])

The above code generates a file, test.csv, with an extra \r at each row, like so:

hi,dude\r\r\nhi2,dude2\r\r\n

instead of the expected

hi,dude\r\nhi2,dude2\r\n

Why is this happening, or is this actually the desired behavior?

1

6 Answers 6

538

Python 3:

The official csv documentation recommends opening the file with newline='' on all platforms to disable universal newlines translation:

with open('output.csv', 'w', newline='', encoding='utf-8') as f:
    writer = csv.writer(f)
    ...

The CSV writer terminates each line with the lineterminator of the dialect, which is '\r\n' for the default excel dialect on all platforms because that's what RFC 4180 recommends.


Python 2:

On Windows, always open your files in binary mode ("rb" or "wb"), before passing them to csv.reader or csv.writer.

Although the file is a text file, CSV is regarded a binary format by the libraries involved, with \r\n separating records. If that separator is written in text mode, the Python runtime replaces the \n with \r\n, hence the \r\r\n observed in the file.

See this previous answer.

Sign up to request clarification or add additional context in comments.

2 Comments

When I use the above code, I only get \r newlines, there is no \n...
With Python 3, you could also use codecs.open without having to specify a newline ending, as stated in doc: "If encoding is not None, then the underlying encoded files are always opened in binary mode. No automatic conversion of '\n' is done on reading and writing."
290

While @john-machin gives a good answer, it's not always the best approach. For example, it doesn't work on Python 3 unless you encode all of your inputs to the CSV writer. Also, it doesn't address the issue if the script wants to use sys.stdout as the stream.

I suggest instead setting the 'lineterminator' attribute when creating the writer:

import csv
import sys

doc = csv.writer(sys.stdout, lineterminator='\n')
doc.writerow('abc')
doc.writerow(range(3))

That example will work on Python 2 and Python 3 and won't produce the unwanted newline characters. Note, however, that it may produce undesirable newlines (omitting the LF character on Unix operating systems).

In most cases, however, I believe that behavior is preferable and more natural than treating all CSV as a binary format. I provide this answer as an alternative for your consideration.

6 Comments

Can you give an example of the problem that arises if you don't "encode all of your inputs to the CSV writer"?
BEWARE: using this means \r is no longer escaped! Looks like this is bug in csvwriter, but as it stands, outputting non-conformant CSV means this is not the way to go.
This solved the ^M problem for me while the accepted answer's 2 suggestions did not work.
BTW, I was wondering the same as @Stephen, and apparently "it doesn't work on Python 3 unless you encode" refers to the 2010 version of the other answer, which recommended open(..., 'wb') without saying it applies to Python 2 only. I don't believe it's actually possble to have the csvwriter work with a 'wb' file object in Python 3.
Finally I think that "it may produce undesirable newlines (omitting the LF character on Unix operating systems)." was supposed to mean that with the lineterminator='\n' hack, the excel dialect will use \n on Unix, rather than \r\n like it's supposed to.
|
67

In Python 3 (I haven't tried this in Python 2), you can also simply do

with open('output.csv','w',newline='') as f:
    writer=csv.writer(f)
    writer.writerow(mystuff)
    ...

as per documentation.

More on this in the doc's footnote:

If newline='' is not specified, newlines embedded inside quoted fields will not be interpreted correctly, and on platforms that use \r\n linendings on write an extra \r will be added. It should always be safe to specify newline='', since the csv module does its own (universal) newline handling.

2 Comments

Why wouldn't this be the default behavior?
@MarcStober because for the majority of opened files you want newlines translated to the platform default. You only ever want to set newline='' when you need full control over how line terminators are handled. Like when writing CSV data that’s compliant with the RFC. Note that it is not the CSV module that opens the file here.
16

You can introduce the lineterminator='\n' parameter in the csv writer command.

import csv
delimiter='\t'
with open('tmp.csv', '+w', encoding='utf-8') as stream:
    writer = csv.writer(stream, delimiter=delimiter, quoting=csv.QUOTE_NONE, quotechar='',  lineterminator='\n')
    writer.writerow(['A1' , 'B1', 'C1'])
    writer.writerow(['A2' , 'B2', 'C2'])
    writer.writerow(['A3' , 'B3', 'C3'])

1 Comment

With Python 3.5.2, this was the only thing that worked for me (well, I used just lineterminator='\n'); the CSV module seemed to be the origin of \r\n. No set of arguments to open had any effect.
2

You have to add attribute newline="\n" to open function like this:

with open('file.csv','w',newline="\n") as out:
    csv_out = csv.writer(out, delimiter =';')

2 Comments

No, you need to Sennewline='' and give the CSV module full control over how line terminators are written. The CSV format uses \r\n terminators regardless of the OS default lone terminator.
newline='' and newline='\n' have the exact same effect when opening a file for writing according to the docs so I don't think this answer is adding anything
2

Note that if you use DictWriter, you will have a new line from the open function and a new line from the writerow function. You can use newline='' within the open function to remove the extra newline.

3 Comments

This has nothing to do with DictWriter. DictWriter is a wrapper class around CSV.writer() and it doesn’t add newlines. There are no “extra newlines”.
@MartijnPieters There arent, after doing exactly that.
@Spartan: not because you are using DictWriter however. Because you are using the csv module, it also applies to csv.writer().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.