You need to manually replace newlines with \n using the replace method.

Set the lineterminator option to the desired character sequence. More info on what else is available is in the docs.

with open('csvfile.csv', 'w') as csvOutput:
    writer = csv.writer(csvOutput, delimiter='|', escapechar=' ', quoting=csv.QUOTE_NONE, lineterminator='\n')

    for row in data:
        writer.writerow([s.replace('\n', '\\n').encode('utf-8') for s in row])
Answer from Jeff Mercado on Stack Overflow
🌐
Python
docs.python.org › 3 › library › csv.html
csv — CSV File Reading and Writing
Any other optional or keyword arguments are passed to the underlying writer instance. Note that unlike the DictReader class, the fieldnames parameter of the DictWriter class is not optional. If the argument passed to fieldnames is an iterator, it will be coerced to a list. ... import csv with open('names.csv', 'w', newline='') as csvfile: fieldnames = ['first_name', 'last_name'] writer = csv.DictWriter(csvfile, fieldnames=fieldnames) writer.writeheader() writer.writerow({'first_name': 'Baked', 'last_name': 'Beans'}) writer.writerow({'first_name': 'Lovely', 'last_name': 'Spam'}) writer.writerow({'first_name': 'Wonderful', 'last_name': 'Spam'})
Discussions

python - How to store strings in CSV with new line characters? - Data Science Stack Exchange
My question is: what are ways I can store strings in a CSV that contain newline characters (i.e. \n), where each data point is in one line? Sample data This is a sample of the data I have: data ... More on datascience.stackexchange.com
🌐 datascience.stackexchange.com
July 22, 2018
newline in text fields with python csv writer - Stack Overflow
when parsing rows to a csv file with csv module, if \n is present in field text this will be creating a newline in the resulting csv file. Consider the following code: import csv field_names=['id', ' More on stackoverflow.com
🌐 stackoverflow.com
csv writer: append doesn't go to new line
The problem is not in your code, it's in your CSV file. text files (including CSV files) traditionally end in a newline, so that it's ready for data to be appended to it. For some reason your csv is breaking that tradition, and that's why you see this error. Easiest solution is to edit your CSV file and add the newline to the end. More on reddit.com
🌐 r/learnpython
3
2
January 26, 2021
What does the `newline=" "` argument do?
Could somebody please explain to me in layman’s terms, what the newline = " " argument does? Documentation is written in a language which only takes me down a rabbit hole of words I don’t understand yet. More on discuss.codecademy.com
🌐 discuss.codecademy.com
0
30
January 30, 2019
🌐
Reddit
reddit.com › r/learnpython › how to remove '\r\n' from the csv records being written?
r/learnpython on Reddit: How to remove '\r\n' from the csv records being written?
July 30, 2015 -

I am running the script on a Windows 7 machine using Python 3.4.1. The script runs correctly and produces a csv file, the only problem is at the end of each line is a '\r\n' which causes an extra blank line to appear when displayed in Excel. How do get remove the extra blank line?

import pyodbc
import csv

connect = pyodbc.connect('driver={SQL Server Native       Client 10.0};SERVER=xxxxx-7-   VM;DATABASE=DEMO_xxxx_TEST;UID=DEMO_xxxx_TEST;PWD=password')

cursor = connect.cursor()

cursor.execute('''select Report_name
                    ,UserID
                    ,FieldName
                    ,XPos
                    ,YPos
                    ,Hidden
                    ,Picture
              from  Rpt_Nudge_2
              where Report_Name = 'UB04' and UserID = 'myid' and YPos > 8886 and YPos < 9888
              order by YPos, XPos''')

col_names = [i[0] for i in cursor.description]
print(col_names)

nudge = cursor.fetchall()

with open('UB04_nudge.csv', 'w') as csvfile:
    fileout = csv.writer(csvfile)
    row = fileout.writerow(col_names)
    for line in nudge:
        fileout.writerow(line)

connect.close()
Top answer
1 of 2
19

Here is a simple solution: Replace all \n with \\n before saving to CSV. This will preserve the newline characters.

df.loc[:, "Column_Name"] = df["Column_Name"].apply(lambda x: x.replace('\n', '\\n'))
df.to_csv("df.csv", index=False)
2 of 2
10

I assume that you want to keep the newlines in the strings for some reason after you have loaded the csv files from disk. Also that this is done again in Python. My solution will require Python 3, although the principle could be applied to Python 2.

The main trick

This is to replace the \n characters before writing with a weird character that otherwise wouldn't be included, then to swap that weird character back for \n after reading the file back from disk.

For my weird character, I will use the Icelandic thorn: Þ, but you can choose anything that should otherwise not appear in your text variables. Its name, as defined in the standardised Unicode specification is: LATIN SMALL LETTER THORN. You can use it in Python 3 a couple of ways:

    weird_literal = 'þ'
    weird_name = '\N{LATIN SMALL LETTER THORN}'
    weird_char = '\xfe'  # hex representation
    weird_literal == weird_name == weird_char  # True

That \N is pretty cool (and works in python 3.6 inside formatted strings too)... it basically allows you to pass the Name of a character, as per Unicode's specification.

An alternative character that may serve as a good standard is '\u2063' (INVISIBLE SEPARATOR).

Replacing \n

Now we use this weird character to replace '\n'. Here are the two ways that pop into my mind for achieving this:

  1. using a list comprehension on your list of lists: data:

     new_data = [[sample[0].replace('\n', weird_char) + weird_char, sample[1]]
                  for sample in data]
    
  2. putting the data into a dataframe, and using replace on the whole text column in one go

     df1 = pd.DataFrame(data, columns=['text', 'category'])
     df1.text = df.text.str.replace('\n', weird_char)
    

The resulting dataframe looks like this, with newlines replaced:

               text              category
0         some text in one line      1   
1  text withþnew line character      0   
2    another newþline character      1   

Writing the results to disk

Now we write either of those identical dataframes to disk. I set index=False as you said you don't want row numbers to be in the CSV:

FILE = '~/path/to/test_file.csv'
df.to_csv(FILE, index=False)

What does it look like on disk?

text,category

some text in one line,1

text withþnew line character,0

another newþline character,1

Getting the original data back from disk

Read the data back from file:

new_df = pd.read_csv(FILE)

And we can replace the Þ characters back to \n:

new_df.text = new_df.text.str.replace(weird_char, '\n')

And the final DataFrame:

new_df
               text               category
0          some text in one line      1   
1  text with\nnew line character      0   
2    another new\nline character      1   

If you want things back into your list of lists, then you can do this:

original_lists = [[text, category] for index, text, category in old_df_again.itertuples()]

Which looks like this:

[['some text in one line', 1],
 ['text with\nnew line character', 0],
 ['another new\nline character', 1]]
🌐
SSOJet
ssojet.com › escaping › csv-escaping-in-python
CSV Escaping in Python | Escaping Techniques in Programming
Python's built-in csv module expertly manages these rules, automatically quoting fields as needed during writing and correctly interpreting them when reading. ... import csv data = [['Product', 'Price'], ['Laptop', '1,200.00'], ['Keyboard', '75.50']] with open('inventory.csv', 'w', newline='') as file: writer = csv.writer(file) writer.writerows(data)
🌐
Python
bugs.python.org › issue15927
Issue 15927: csv.reader() does not support escaped newline when quoting=csv.QUOTE_NONE - Python tracker
September 12, 2012 - This issue tracker has been migrated to GitHub, and is currently read-only. For more information, see the GitHub FAQs in the Python's Developer Guide · This issue has been migrated to GitHub: https://github.com/python/cpython/issues/60131
Find elsewhere
Top answer
1 of 2
2

The created file is a valid CSV file - parsers should be able to identify that a pair of quotes is open when they find a newline character.

If you want to avoid these characters for being able to see then with a normal, non CSV aware, text editor, then you have to escape the newlines, so that the data output is transformed from the real newline character (a single byte with decimal value 10 (\x0a or \n) ) to two printable character sequence: \ and n (2 bytes with decimal values 92 and 110) - or any other sequence of your choice.

On the Python side, that is simply achievable with a str.replace call. However, although you will then see the CSV data rows in the same "physical TXT data rows", in a similar manner applications that will later read this file as data, like a spreadsheet or other Python scripts, won't recognize these sequences as "newlines": you will have to replace them again for newlines after being read (or just keep the modified data and work with it).

tbl_name= 'testnewlines'

with open(tbl_name+'.csv','w', newline='',  encoding='utf-8') as f:
    writer=csv.DictWriter(f,fieldnames=field_names,delimiter='|')
    writer.writeheader()
    for d_row in data_rows:
        # the next three lines could be written as a comprehension.
        # I am unwinding them for clarity
        new_row = {}
        for key, value in data_rows.items():
            new_row[key] = value.replace("\n", "\\n")  if isinstance(value, str) else value
            # "\\n" escapes the "\" itself so it is a literal "\" 
            # character, and not a character escaping the "n"
        writer.writerow(new_row)

Just to emphasize with other words: this will create a file that is more neat to look at with a text editor, but will not preserve the recorded data for a round-trip: it will require a custom-step after reading to undo this replacement.

2 of 2
0

I would do it by simply escaping the (\n).

Replace this :

    for d_row in data_rows:
        writer.writerow(d_row)

By this :

    for d_row in data_rows:
        writer.writerow({k: v.replace('\n', '\\n') if isinstance(v, str)
                         else v for k, v in d_row.items()})

Output (.csv) :

id|number|scope
100001|a01|row1 test \n\nrow1 test\n\nrow1 test
100002|a02|row2 test \n\nrow2 test\n\nrow2 test
🌐
GitConnected
levelup.gitconnected.com › manage-newline-breaks-in-csv-files-with-python-160fefb9ac45
Manage newline breaks in CSV files with Python | by Stephen David-Williams | Level Up Coding
November 27, 2023 - Join Medium for free to get updates from this writer. ... Note⚠️: The following steps are shown for a Windows machine using ‘\r\n’ for newlines. Replace with ‘\n’ if you’re on a Unix-based machine instead. You can swap newlines with a space or another placeholder of your choice: df["Description"] = df["Description"].str.replace('\\r\\n', ' ', regex=True) df.to_csv("new_file.csv", sep='|', index=False, quoting=csv.QUOTE_NONE, escapechar='\\\\')
🌐
KnowledgeHut
knowledgehut.com › https://www.knowledgehut.com › tutorials › programming tutorials
Python CSV Tutorial: Read, Write & Manipulate CSV Files in Python
A list of tuples is then written to file using writerow() method. >>> import csv >>> marks=[('Seema',22,45),('Anil',21,56),('Mike',20,60)] >>> csvfile=open(marks.csv','w', newline='') >>> obj=csv.writer(csvfile) >>> for row in marks: obj.writerow(row) >>> csvfile.close()
🌐
Medium
medium.com › @richard.jones › unusual-newlines-in-csvs-888d2da838f4
Unusual newlines in CSVs. We were debugging an issue with a… | by Richard D Jones | Medium
June 11, 2018 - As the csv writer does not recognise \u2029 as a newline character, it does not wrap the quotes around the string like it would if it contained\n. The fix is easy, when constructing your writer in python you should do it like this:
🌐
Reddit
reddit.com › r/learnpython › csv writer: append doesn't go to new line
r/learnpython on Reddit: csv writer: append doesn't go to new line
January 26, 2021 -

So, basically, I've got this code:

new_list_csv = []

def add_it():
    #gets the values from Entry
    #three different tk Entrys generate three different values
    name= self.e.get()
    ex= self.e_x.get()
    ey= self.e_y.get()
    #adds them to the new list
    new_list_csv.append(name)
    new_list_csv.append(ex)
    new_list_csv.append(ey)
    #appends new characters to csv file
    with open ('chr_list_copy.txt', 'a', newline='') as write_obj:   
        csv_writer = csv.writer(write_obj)
        csv_writer.writerow(new_list_csv)

and the csv file looks like this:

name,x,y
Ergo,1,1
Sum,5,5
Name12,1,2
Name34,3,4
Name56,5,6
Name78,7,8
Name910,9,10
Name1112,11,12
Name1314,13,14

if I try and add [Otto,6,9], I get:

name,x,y
[...]
Name1314,13,14Otto,6,9

instead of:

name,x,y
[...]
Name1314,13,14
Otto,6,9

I've used this very same structure for the rest of my code, but in this specific instance, it doesn't work.

🌐
Codecademy Forums
discuss.codecademy.com › computer science
What does the `newline=" "` argument do? - Computer Science - Codecademy Forums
January 30, 2019 - Could somebody please explain to me in layman’s terms, what the newline = " " argument does? Documentation is written in a language which only takes me down a rabbit hole of words I don’t understand yet.
🌐
Python
docs.python.org › 3.4 › library › csv.html
14.1. csv — CSV File Reading and Writing — Python 3.4.10 documentation
July 16, 2019 - Return a writer object responsible for converting the user’s data into delimited strings on the given file-like object. csvfile can be any object with a write() method. If csvfile is a file object, it should be opened with newline='' [1]. An optional dialect parameter can be given which is ...
🌐
GitHub
github.com › python › cpython › issues › 60131
csv.reader() does not support escaped newline when quoting=csv.QUOTE_NONE · Issue #60131 · python/cpython
September 12, 2012 - assignee = None closed_at = <Date 2013-03-20.02:44:33.925> created_at = <Date 2012-09-12.04:49:29.368> labels = ['type-bug', 'library'] title = 'csv.reader() does not support escaped newline when quoting=csv.QUOTE_NONE' updated_at = <Date 2018-01-12.10:17:18.417> user = 'https://bugs.python.org/kalaxy' bugs.python.org fields: activity = <Date 2018-01-12.10:17:18.417> actor = 'xflr6' assignee = 'none' closed = True closed_date = <Date 2013-03-20.02:44:33.925> closer = 'r.david.murray' components = ['Library (Lib)'] creation = <Date 2012-09-12.04:49:29.368> creator = 'kalaxy' dependencies = [] f
Author   python
🌐
Stack Overflow
stackoverflow.com › questions › 74646678 › python-csv-writer-keep-escape-character
python CSV writer keep escape character - Stack Overflow
I'm not sure, but I guess csv.writer(csvwriter, csv.QUOTE_ALL) can help you. ... import csv with open("input.csv", "r") as f_in, open("output.csv", "w") as f_out: reader = csv.reader(f_in, delimiter=",", quotechar='"', escapechar="\\") writer = csv.writer( f_out, delimiter=",", quotechar='"', escapechar="\\", doublequote=False, ) writer.writerow(next(reader)) for row in reader: row[3] = row[3][:500] writer.writerow(row)
🌐
Reddit
reddit.com › r/learnpython › changing carriage return to newline in a csv file using python
r/learnpython on Reddit: Changing carriage return to newline in a csv file using python
November 12, 2019 -

For a uni assignment, I need to process a csv file. However these csv files were written such that the EOL character in every case is a carriage return (\r) character. The assignment prompt says that I cannot read in the file using the csv module as it will not recognise the \r character and thus the requirement of the assignment is that, in my Python script, I change the carriage return to a newline or any other EOL character that Python's csv module can recognise as a valid EOL. How would I do this? Also why doesn't the csv module recognise the carriage return? (Sorry for poor English and/or bad formatting)

🌐
Python Morsels
pythonmorsels.com › newlines-and-escape-sequences
Newlines and escape sequences in Python - Python Morsels
February 10, 2025 - writer.writerows(cities) ... So when writing a file using Python's csv module, you're expected to always specify newline="" when opening the file you're writing to, to make sure that you don't accidentally double up your carriage returns on Windows.
Top answer
1 of 6
540

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.

2 of 6
291

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.

Top answer
1 of 4
3

Based on your comments, the data you're being served doesn't actually include carriage returns or newlines, it includes the text representing the escapes for carriage returns and newlines (so it really has a backslash, r, backslash, n in the data). It's otherwise already in the form you want, so you don't need to involve the csv module at all, just interpret the escapes to their correct value, then write the data directly.

This is relatively simple using the unicode-escape codec (which also handles ASCII escapes):

import codecs  # Needed for text->text decoding

# ... retrieve data here, store to res ...

# Converts backslash followed by r to carriage return, by n to newline,
# and so on for other escapes
decoded = codecs.decode(res, 'unicode-escape')

# newline='' means don't perform line ending conversions, so you keep \r\n
# on all systems, no adding, no removing characters
# You may want to explicitly specify an encoding like UTF-8, rather than
# relying on the system default, so your code is portable across locales
with open(title, 'w', newline='') as f:
    f.write(decoded)

If the strings you receive are actually wrapped in quotes (so print(repr(s)) includes quotes on either end), it's possible they're intended to be interpreted as JSON strings. In that case, just replace the import and creation of decoded with:

import json


decoded = json.loads(res)
2 of 4
0

If I understand your question correctly, can't you just replace the string? with open(title, 'w') as f: f.write(res.replace("¥r¥n","¥n"))