99

我有一个将列表写入文件的程序。该列表是一个以管道分隔的行的列表,这些行应该像这样写入文件:

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)
4

8 回答 8

79

对于 Python 新手来说,这实际上是一个很常见的问题——尤其是因为在标准库和流行的第三方库中,一些读取函数会去除换行符,但几乎没有写入函数(除了log-related 的东西)会添加它们。

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

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

或者

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

任何一个都是正确的,当然你甚至可以编写自己的 writelinesWithNewlines 函数来包装它......</p>

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

如果您可以首先创建/保留换行符,那就更好了——正如 Greg Hewgill 的建议:

line_list.append(new_line + "\n")

如果您可以在比原始文本行更高的级别上工作,那就更好了,例如,通过使用标准库中的csv模块,正如 esuaro 所建议的那样。

例如,在定义 之后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)

最后,您的设计是“打开一个文件,然后建立一个要添加到文件中的行列表,然后一次将它们全部写入”。如果您要从顶部打开文件,为什么不逐行编写呢?无论您是使用简单的 writes 还是 a csv.writer,它都会让您的生活更简单,并且您的代码更易于阅读。(有时可能出于简单、高效或正确性的原因一次性编写一个文件——但是一旦你openwrite. - 一次。)

于 2012-12-05T18:52:01.497 回答
53

状态的文档writelines()

writelines()不添加行分隔符

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

    line_list.append(new_line + "\n")

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

于 2012-12-05T18:44:58.233 回答
34

正如其他人所指出的,writelines是用词不当(荒谬的是,它没有在每行的末尾添加换行符)。

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

with open(dst_filename, 'w') as f:
    f.writelines(s + '\n' for s in lines)
于 2018-05-07T22:39:28.433 回答
9

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

items = ['abc', '123', '!@#']
items = map(lambda x: x + '\n', items)
w.writelines(items)
于 2016-11-13T14:52:33.133 回答
6

学分Brent Faust


Python >= 3.6 带格式字符串:

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

lines可以是一个set

如果您是老派(像我一样),您可以f.write('\n')在第二行下方添加。

于 2021-04-12T15:37:14.960 回答
5

正如其他人所提到的,与方法名称所暗示的相反,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(写入文件)是那种事情实际上很重要的时候。希望这对某人有帮助!

于 2017-03-13T05:21:22.320 回答
2

正如我们在这里已经确立的那样,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)

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

于 2018-11-23T20:13:52.253 回答
1

由于我们只想分隔行,而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)

你就完成了。

于 2020-09-24T20:17:10.917 回答