Siedler
Siedler

Reputation: 97

Why does Python file.write() unexpectedly add a newline to every line?

I would like to write strings into a file during a loop:

with open("dump.txt", "w+") as file:
    for x in range(1, 10):
        file.write(str(x) + "\r\n")

If I open dump.txt in Notepad on Windows, I get what I expect:

1
2
3
4
5
6
7
8
9

I have to add the \r\n at the end of each line, because otherwise I get 123456789 (all numbers in one line).

When I inspect my dump.txt in Notepad++ I can see that I get an extra CRLF after every line:

1 CRLF
CRLF
2 CRLF
CRFL
etc.

When I read dump.txt back into python and loop through the files, the extra LF are output:

import sys

with open("dump.txt", "r") as infile:
    for line in infile:
         sys.stdout.write(line)

C:\...\Python\Python38-32\python.exe C:/.../script.py
1

2

3

If I create a new file using Notepad on Windows and just enter the numbers 1 through 9, hitting enter after each line, python reads it in correctly. In Notepad++ I also don't see any extra CRLF characters.

import sys 

with open("dump2.txt", "r") as infile:
    for line in infile:
         sys.stdout.write(line)

C:\...\Python\Python38-32\python.exe C:/.../script2.py
1
2
3
...
9

My question is: What am I missing here? Python seems to add a second CRLF with each file.write(), but only if the string to be written already ends with a "\r\n". This is a very odd behavior.

I would like to write my strings line by line ending either with my explicit "\r\n" or even better with the EOL character for the platform on which the script is running, just as if I had just manually created a txt file using Notepad..

Your help is much appreciated!

Upvotes: 3

Views: 5824

Answers (4)

aristila
aristila

Reputation: 1

You should define what you want to use as newline in the open command with

newline='\n'

e.g.

with open("dump.txt", "w+", newline="\n") as file

Upvotes: 0

Emporio Argani
Emporio Argani

Reputation: 1

I encountered the same issue.

I fixed it like this

#string to write to a file
string_to_write = string_to_write.replace('\r\n','\r')

This did the job for me.

Upvotes: 0

Ture Pålsson
Ture Pålsson

Reputation: 6776

Python uses the convention, inherited from C, that the newline character internally is always a single LF (sometimes written as \n), regardless of what the platform convention happens to be. When a file is opened in text mode, which is the default, data is automagically converted to/from the platform standard on writing/reading.

You're on Windows, where the end-of-line convention is CR+LF. When you write '\r\n' (i.e, CR + LF), this gets converted to CR + CR + LF. When you read this back, the CR+LF pairs get converted to LF, and the "lone" CR:s also get converted to LF:s!

For more reading, start with the documentation for the openfunction and follow the links.

Upvotes: 3

coderman1234
coderman1234

Reputation: 230

CRLF in Notepad ++ means "carriage return", or in Python, it means \r. If you want to remove them on the write, then just put \n instead.

Upvotes: 2

Related Questions