-1

The following code adds an extra blank line ("\r") to every write, whereas it is supposed to just write one ("\r\n") at the end of every write. I have no idea why.

import os

with open("output", "w", encoding="utf-8") as f:
    for i in range(10):
        f.write(str(i) + os.linesep)

It writes to the file: "0\r\r\n1\r\r\n2...9\r\r\n". I am using Python 3.9.16 on Windows. Am I missing something here?

Edit: I tested without encoding="utf-8" as well, and still the same issue happens.

Diamond
  • 598
  • 5
  • 15
  • I could not find "https://stackoverflow.com/questions/4025760/python-file-write-creating-extra-carriage-return", either through Google search or by the suggested duplicates that StackOverflow suggests, but that does answer my question as I closed the question myself. I don't understand the reason for the downvote really, but as you wish! – Diamond Apr 28 '23 at 01:23

2 Answers2

2

You don't need to use os.linesep directly. Opening a file for writing in text mode already does newline translation unless you specify a newline setting that turns it off.

In fact, the os.linesep docs specifically warn you not to do this:

Do not use os.linesep as a line terminator when writing files opened in text mode (the default); use a single '\n' instead, on all platforms.

user2357112
  • 260,549
  • 28
  • 431
  • 505
  • Oh, weird! So, newline=None actually translates to newline="\r"? – Diamond Apr 28 '23 at 00:53
  • @Diamond: No, in write mode, `newline=None` is more like `newline=os.linesep`. (In read mode, `newline=None` enables universal newlines, which does not behave like any other `newline` setting.) – user2357112 Apr 28 '23 at 00:54
  • But here linesep is "\r\n", not "\n". In that case , the output should be "0\r\n\r\n1...". – Diamond Apr 28 '23 at 00:55
  • @Diamond: If you try to write `'\r\n'` to the file, the `\n` gets translated, and you end up with `'\r\r\n'`. – user2357112 Apr 28 '23 at 00:56
  • I don't get it. The documentation says: On input, if newline is None, universal newlines mode is enabled. Lines in the input can end in '\n', '\r', or '\r\n', and these are translated into '\n' before being returned to the On output, if newline is None, any '\n' characters written are translated to the system default line separator, os.linesep. What I get from this is that \r\n in my linesep is translated into \n and then on the output, "\n" is transleted back into "\r\n", which is the os.linesep. How is that? – Diamond Apr 28 '23 at 01:02
  • Yes, so when you try to write `'\r\n'` to the file, the `\r` is left there and the `\n` is replaced with `\r\n`, leaving you with `\r\r\n`. – user2357112 Apr 28 '23 at 01:03
  • But it says "\r\n" is translated into "\n". So, the doc is wrong apparently? – Diamond Apr 28 '23 at 01:05
  • @Diamond: You are *writing* to the file, not reading. – user2357112 Apr 28 '23 at 01:06
  • And this stuff is one reason why I just use `print`. – Kelly Bundy Apr 28 '23 at 01:31
-1
import os

with open("output", "w", encoding="utf-8") as f:
    for i in range(10):
        f.write(str(i))
        f.write('\n')
  • 1
    Welcome to StackOverflow! While this *may* be a real answer, it would be beneficial to everyone if you could explain how it works and why it works. Thanks! – M Z Apr 28 '23 at 04:56