Writelines写的行没有换行符,只填充文件


77

我有一个将列表写入文件的程序。该列表是由管道分隔的行的列表,这些行应按如下所示写入文件:

123|GSV|Weather_Mean|hello|joe|43.45
122|GEV|temp_Mean|hello|joe|23.45
124|GSI|Weather_Mean|hello|Mike|47.45

但是它写了他们这行啊:

123|GSV|Weather_Mean|hello|joe|43.45122|GEV|temp_Mean|hello|joe|23.45124|GSI|Weather_Mean|hello|Mike|47.45

该程序将所有行写成一行,而没有任何换行符。我认为写行应该在文件下写行,而不是将所有内容都写到一行。

fr = open(sys.argv[1], 'r') # source file
fw = open(sys.argv[2]+"/masked_"+sys.argv[1], 'w') # Target Directory Location

for line in fr:
    line = line.strip()
    if line == "":
        continue
    columns = line.strip().split('|')
    if columns[0].find("@") > 1:
        looking_for = columns[0] # this is what we need to search
    else:
        looking_for = "Dummy@dummy.com"
    if looking_for in d:
        # by default, iterating over a dictionary will return keys
            new_line = d[looking_for]+'|'+'|'.join(columns[1:])
            line_list.append(new_line)
    else:
        new_idx = str(len(d)+1)
        d[looking_for] = new_idx
        kv = open(sys.argv[3], 'a')
        kv.write(looking_for+" "+new_idx+'\n')
        kv.close()
        new_line = d[looking_for]+'|'+'|'.join(columns[1:])
        line_list.append(new_line)
fw.writelines(line_list)

看来您没有将追加"\n"到您的line_list
罗希特·贾因

2
您可以看看csv
esauro

在哪里添加“ \ n”?是否将其添加到列表对象?
user836087

Answers:


59

对于Python的新手来说,这实际上是一个非常普遍的问题-特别是因为在标准库和流行的第三方库中,一些阅读功能会删除换行符,但是几乎没有书写功能(与log相关的东西除外)会添加它们。

因此,有很多Python代码可以执行以下操作:

fw.write('\n'.join(line_list) + '\n')

要么

fw.write(line + '\n' for line in line_list)

哪一种是正确的,当然您甚至可以编写自己的writelinesWithNewlines函数来包装它……

但是,只有在无法避免的情况下,才应该这样做。

最好首先创建/保留换行符,如Greg Hewgill的建议:

line_list.append(new_line + "\n")

如esuaro所建议的,例如,可以使用标准库中的csv模块,则可以比文本的原始行更高级地工作,甚至更好。

例如,在定义之后fw,您可以执行以下操作:

cw = csv.writer(fw, delimiter='|')

然后,代替此:

new_line = d[looking_for]+'|'+'|'.join(columns[1:])
line_list.append(new_line)

你来做这件事:

row_list.append(d[looking_for] + columns[1:])

最后,代替这个:

fw.writelines(line_list)

你来做这件事:

cw.writerows(row_list)

最后,您的设计是“打开文件,然后建立要添加到文件中的行列表,然后一次写入所有行”。如果要打开该文件,为什么不只一行一行地写呢?无论您使用的是简单写入还是csv.writer,它都将使您的生活更简单,并且代码也更易于阅读。(有时出于简单,效率或正确性的原因,一次全部写入一个文件,但是一旦您将open所有操作从移到程序的另一端write,您就几乎失去了所有好处。 -一次)。


46
所有这些都是因为python并没有做到明显writelines
StephenBoesch

33
哇。在Python方面,这是荒谬的行为:readlines()应该删除换行符,但不删除换行符,而writelines()应该添加换行符,但不删除换行符。具有读取行和写入行的全部目的是使您可以轻松地读取和写入列表。轻气!
詹姆斯

6
是否像f.writelines(lines,end ='\ n')这样的PEP值得吗?
约翰·林

在第二个示例中应为fw.writelines(line_list中的line +'\ n')
Dan

46

对文档writelines()状态:

writelines() 不添加行分隔符

因此,您需要自己添加它们。例如:

    line_list.append(new_line + "\n")

每当您将新项目附加到时line_list


+1。这是最简单的解决方案,如果OP不想切换到更高级别的东西,那么几乎肯定是最合适的解决方案csv
abarnert

85
仅仅为了“匹配”阅读行而为函数起的可怕名字。
桑迪·查普曼

24
比可怕的名字更糟:可怕的功能
StephenBoesch

24

正如其他人指出的那样,它writelines是一个用词不当的名称(可笑的是它没有在每行的末尾添加换行符)。

为此,将其显式添加到每一行:

with open(dst_filename, 'w') as f:
    f.writelines(s + '\n' for s in lines)

8

writelines()不添加行分隔符。您可以通过在每个字符串的末尾map()添加一个新的\n(换行符)来更改字符串列表。

items = ['abc', '123', '!@#']
items = map(lambda x: x + '\n', items)
w.writelines(items)

2

正如其他人所提到的,并且与方法名称的含义相反,该方法writelines没有添加行分隔符。这是发电机的教科书箱。这是一个人为的示例:

def item_generator(things):
    for item in things:
        yield item
        yield '\n'

def write_things_to_file(things):
    with open('path_to_file.txt', 'wb') as f:
        f.writelines(item_generator(things))

好处:显式添加换行符,而无需修改输入或输出值或进行任何混乱的字符串连接。而且,至关重要的是,不会在内存中创建任何新的数据结构。IO(写入文件)是指这种情况实际上很重要的时候。希望这对某人有帮助!


1

正如我们在这里已建立的一样,writelines请勿为您添加换行符。但是,每个人似乎都缺少的是,当用作直接的“对手”时,不必一定要使用它,readlines()并且最初的阅读可以使换行符持久化!

当您打开文件以二进制模式(通过'rb'readlines()读取时,然后用于将文件内容提取到内存中(按行分割),换行符仍附加在行尾!因此,如果您随后将其写回,则可能不需要writelines附加任何内容!

因此,如果执行以下操作:

with open('test.txt','rb') as f: lines=f.readlines()
with open('test.txt','wb') as f: f.writelines(lines)

您应该最终获得与开始时相同的文件内容。


以及什么时候您只想读回一个文件呢?
私人

1
从字面上看,您正在以代码为例。当您读取文件并将其写回时,我没有提供虚假上下文和无关的示例代码。在通常情况下,您将需要修改内容。或者,您可能正在将源文件“复制” /调整为目标文件。重点是对应的readlines / writelines隐式处理了此问题。
BuvinJ

抱歉,我不是要坚持这个问题。多数情况下,当我读取文件并写回该文件或另一个文件时,我调用的方法之一就是.strip'.rstrip()`,因此在我的工作流中这永远不会发生。
私人

Np。我经常做同样的事情,但是如果您登陆此页面,则可能希望在某些用例中更改这种做法,在这种情况下,您想保留行尾,可以避免记住这些帖子而显式地附加它们。
BuvinJ

0

由于我们只想分隔行,而writelinespython中的函数不支持在行之间添加分隔符,因此我在下面编写了最适合此问题的简单代码:

sep = "\n" # defining the separator
new_lines = sep.join(lines) # lines as an iterator containing line strings

最后:

with open("file_name", 'w') as file:
    file.writelines(new_lines)

到此为止。


由于您要发布的是一个较旧问题的答案,因此最好使用一些代码以及使用该代码所产生的输出来支持所声称的答案。
灰色

如果事先将行连接到单个字符串,则调用writelines毫无意义。
达利博尔·菲卢斯(Dalbor Filus)'20年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.