【问题标题】:'\r' not working as `lineterminator` within Python `csv.writer()`'\r' 在 Python `csv.writer()` 中不能作为`lineterminator` 工作
【发布时间】:2021-01-31 05:36:00
【问题描述】:

我在 Windows 上工作。我有一个 Python 文件来创建一个新的 CSV 文件,我使用Notepad(甚至通过Microsoft Excel)查看它。

import csv
data = [['fruit','quantity'], ['apple',5], ['banana',7],['mango',8]]
with open('d:\lineter.csv', 'w') as l:
    w = csv.writer(l,delimiter='|', lineterminator='\r')
    w.writerows(data)

记事本中的结果文件:

fruit|quantityapple|5banana|7mango|8

回车\r 是否有效?它的工作方式类似于 记事本 中的lineterminator=''。但在 Excel 中,它的工作方式类似于 '\n'。

输出似乎没有实现回车。当我使用lineterminator 时:

w = csv.writer(l, delimiter='|', lineterminator='*\r*\n')

记事本中的输出是:

fruit|quantity**
apple|5**
banana|7**
mango|8**

这也很明显。

'\r' 如何在 writer() 中的 lineterminator 中工作? 还是那里发生了另一件事?

【问题讨论】:

  • \r 并非所有工具都可以解释为可视化文件,您如何看待文件?
  • 为什么要使用 \r 作为行终止符?如果您阅读csv 文档,您将在csv.writer() 下方的第二个使用示例中看到推荐的设置,用于open() 操作。为什么不/不能使用它?见docs.python.org/3.8/library/csv.html?highlight=csv
  • @barny,我只想知道 '\r' 是否有效。这就是我使用它的原因

标签: python windows csv writer


【解决方案1】:

简短的回答:

何时使用回车(CR,\r)与换行(LF,\n)与两者(CRLF,\r\n)在文本编辑器中显示新行Windows、Mac 和 Linux:

'\r' 如何在 writer() 中的 lineterminator 中工作?

它在csv.writer() 中运行良好。这真的不是 Python、CSV 或 writer 问题。这是一个操作系统的历史差异(实际上,更准确地说是program-specific difference)可以追溯到 1960 年代左右。

或者那里发生了其他事情?

是的,就是这个。

您的记事本版本无法将回车符 (\r) 识别为用于显示新行的字符,因此不会在记事本中这样显示。其他文本编辑器,例如 Sublime Text 3,即使在 Windows 上也可能会。

直到大约 2018 年左右,Windows 和记事本都需要回车 + 换行 (\r\n)一起来显示新行。将此与仅需要 \n 的 Mac 和 Linux 进行对比。

解决方案是在 Windows 上使用 \r\n 换行,在 Mac 或 Linux 上单独使用 \n 换行。您还可以尝试不同的文本编辑器,例如 Sublime Text,查看或编辑文本文件时,或者升级您的 Windows 或记事本版本,如果可能的话,somewhere around the year 2018 Windows 记事本开始接受@ 987654351@ 单独作为有效的旧 Mac 风格的换行符。

(来自 OP 在此答案下的评论):

那为什么要给'\r\n'???

当程序员编写程序时,程序员可以让程序做程序员想让程序做的任何事情。 当 Windows 程序员制作 Windows 和记事本时,他们决定让程序在得到 \r 时不执行任何操作,如果得到 \n 则不执行任何操作,如果得到 \r\n,则执行新行 一起。就是这么简单。该程序完全按照程序员的指示去做,因为他们决定这就是他们希望程序工作的方式。因此,如果您想在 Windows 的旧版(2018 年之前)记事本中添加一个新行,您必须按照程序员的要求来获取它。 \r\n是吗。

这可以追溯到teletypewriters (read the "History" and "Representation" sections here)this page about "teleprinters" / "teletypewriters" / "teletype or TTY machines" 的时代:

打字机或机电打印机可以在纸上打印字符,并执行诸如将回车移回同一行的左边距回车)等操作, 前进到下一行的同一列换行),依此类推。
source;强调)

电传打字机上的机械回车按钮(\r 现在在计算机上)表示:“将回车(打印头)返回到行首”(意思是:页面的最左侧),以及电传打字机上的换行机械机制(\n 现在在计算机上)的意思是:“将纸卷上一行,以便我们现在可以输入下一行。”如果没有机械换行 (\n) 操作,仅回车 (\r) 就会将机械打印头移动到页面的最左侧,并导致您在您输入的单词的顶部右回键入已经输入了! 如果没有回车机械动作(计算机上的\r),单独的换行机械动作(\n)将导致您只需在每个最右边的最后一列中输入页面上的新行,再也无法将打印头返回到页面的左侧!在机电式电传打字机上,必须使用它们两者回车会将打印头带回页面左侧,而换行动作会移动打印前往下一行因此,据推测,Windows 程序员认为保持这一传统是合乎逻辑的,他们决定both 要求\r\ntogether 在一台计算机,因为这就是传统上必须在机电电传打字机上完成的方式

阅读下文了解详情。

详情(较长的答案):

我对正在发生的事情有一些想法,但让我们来看看。我相信我们有两个问题要回答:

  1. \r 是否实际存储到文件中?
  2. 记事本是否真的显示\r,如果没有,为什么不呢?

所以,对于#1。让我们在 Linux 上测试一下Ubuntu 20.04(Focal Fossa):

这个程序:

#!/usr/bin/python3

import csv
data = [['fruit','quantity'], ['apple',5], ['banana',7],['mango',8]]
with open('d:\lineter.csv','w') as l:
    w = csv.writer(l, delimiter='|', lineterminator='\r')
    w.writerows(data)

生成此文件:d:\lineter.csv。如果我在Sublime Text 3 text editor 中打开它,我会看到:

fruit|quantity
apple|5
banana|7
mango|8

到目前为止一切顺利。我们来看看命令行中带有hexdump的字符:

hexdump -c 显示\r 字符,果然!

$ hexdump -c d\:\\lineter.csv
0000000   f   r   u   i   t   |   q   u   a   n   t   i   t   y  \r   a
0000010   p   p   l   e   |   5  \r   b   a   n   a   n   a   |   7  \r
0000020   m   a   n   g   o   |   8  \r
0000028

您也可以使用hexdump -C 以十六进制显示字符,同样,我将文件中的\r 视为十六进制0d 字符,这是正确的。

好的,所以我在 Linux 的 VirtualBox 虚拟机中启动 Windows 10 Professional,然后在记事本中打开相同的文件,然后....它也可以工作!见截图:

但是,请注意我圈出的部分,上面写着“Macintosh (CR)”。我正在运行最新版本的 Windows 10 专业版。 我打赌你使用的是旧版本的记事本,它没有这个修复,你不会在这里说。 这是因为 33 年来记事本没有将回车符或 \r 处理为有效的行尾,因此它不会显示为这样。请参阅此处:Windows Notepad fixed after 33 years: Now it finally handles Unix, Mac OS line endings

由于historical differences dating back to teletypewriters and Morse code(阅读此处的“历史”和“表示”部分),不同的系统决定让他们的文本编辑器以不同的方式处理行尾。来自article just above(已添加重点):

记事本以前只能识别 Windows End of Line (EOL) 字符,特别是回车符(CR、\r、0x0d)和换行符(LF、\n、0x0a)一起。。 p>

对于老式 Mac OS,EOL 字符只是回车符(CR,\r,0x0d)对于 Linux/Unix,它只是换行符(LF,\n, 0x0a)。现代 macOS,自 Mac OS X 以来,遵循 Unix 约定。

所以,我们这里的内容是在文本编辑器中显示为换行符:

  1. 老式 Mac: 仅限 CR (\r)
  2. Windows 记事本直到 ~2018: CR 和 LF 一起 (\r\n)
  3. Linux: 仅限 LF (\n)
  4. 现代 Mac: 仅限 LF (\n)
  5. 现代 Windows 记事本(2018 年及以后):上述任何场景。

因此,对于 Windows,只需始终使用 \r\n 换行,对于 Mac 或 Linux,只需坚持始终使用 \n 作为换行符,除非您试图保证文件的老式(即 2019 年之前 :))Windows 兼容性,在这种情况下,您也应该使用 \r\n 作为换行符。


注意,对于 Sublime Text 3,我只是在 PreferencesSettings 中搜索了首选项,发现了这个设置:

    // Determines what character(s) are used to terminate each line in new files.
    // Valid values are 'system' (whatever the OS uses), 'windows' (CRLF) and
    // 'unix' (LF only).
    "default_line_ending": "system",

因此,要对运行 Sublime Text 的任何操作系统使用约定,默认为“系统”。但是,要在 Sublime Text 中编辑和保存文件时强制 'windows' (CRLF) 行结束,请使用以下命令:

"default_line_ending": "windows",

要强制 Unix(Mac 和 Linux)仅 LF 行尾设置,请使用:

"default_line_ending": "unix",

在记事本编辑器中,我找不到要配置的此类设置。它是一个简单的编辑器,33 年来只支持 Windows 行尾。

补充阅读:

  1. https://en.wikipedia.org/wiki/Teleprinter
  2. https://en.wikipedia.org/wiki/Newline#History
  3. Is a new line = \n OR \r\n?
  4. Why does Windows use CR LF?
  5. [我还需要阅读和学习]Unix & Linux: Why does Linux use LF as the newline character?
  6. [我还需要阅读和学习]Retrocomputing: Why is Windows using CR+LF and Unix just LF when Unix is the older system?

【讨论】:

  • 那么excel哥们呢?
  • 同样对于 Windows,即使我只给出 '\n',我也会得到相同的输出。那为什么要给'\r\n'???
  • Then why to give '\r\n'??? 当程序员编写程序时,程序员可以让程序做程序员想让程序做的任何事情。当 Windows 程序员制作 Windows 和记事本时,他们决定让程序在得到\r 时不执行任何操作,如果得到\n 则不执行任何操作,并且在得到\r\n 时执行新行。就是这么简单。该程序完全按照程序员的指示去做,因为他们决定这就是他们希望程序工作的方式。所以,如果你想在 Windows 中创建一个新行,你必须按照程序员的要求去做才能得到它。 \r\n 是吗。
  • 我认为您真正的意思是电传打字机,而不是打字机。老式的机械打字机有一个杠杆可以移动到下一行,它移动到页面的左侧,并且一口气将纸张推进了一行。早期的 CRT 显示器保留了电传打字机的惯例。
  • 我从来没有用过打字机。 :) 我小时候可能看过一两次,但我从未真正看过一部作品。是的,我一定是弄错了。我需要对打字机做更多的研究,也许还会看一些关于它们如何工作的视频。我打赌有不同类型的打字机,而带有杠杆的打字机可能是后来作为技术进步出现的?无论哪种情况,我都需要对这些细节进行更多研究。但这里真正的关键是:程序员可以做程序员想做的事,他们让 Nodepad 需要 \r\n 来获得新的一行。结束。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-01
  • 2015-09-29
  • 2019-07-31
  • 1970-01-01
  • 1970-01-01
  • 2015-03-19
相关资源
最近更新 更多