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

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

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)
152740 次浏览

writelines()的文件指出:

writelines()不添加行分隔符

So you'll need to add them yourself. For example:

    line_list.append(new_line + "\n")

无论何时向 line_list追加新项。

对于 Python 的新手来说,这实际上是一个相当普遍的问题ーー特别是在标准库和流行的第三方库中,一些阅读函数去掉了换行符,但几乎没有写入函数(除了与 log相关的函数)添加换行符。

因此,现在有很多 Python 代码可以做这样的事情:

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

或者

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

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

But you should only do this if you can't avoid it.

如果你能够首先创建/保留新行,那就更好了ーー正如格雷格•休吉尔(Greg Hewgill)的建议:

line_list.append(new_line + "\n")

而且,如果您能够在比原始文本更高的级别上工作,那就更好了,例如,像 esuaro 建议的那样,使用标准库中的 CSV模块。

For example, right after defining fw, you might do this:

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

Then, instead of this:

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,它都会使你的生活变得更简单,你的代码也更容易阅读。(有时候一次写一个文件可能会有简单、高效或者正确的理由,但是一旦你把 openwrite移到了程序的另一端,你几乎就失去了一次写一个文件的好处。)

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

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

As others have mentioned, and counter to what the method name would imply, writelines does not add line separators. This is a textbook case for a generator. Here is a contrived example:

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 (写入文件)是指这类事情实际上很重要的时候。希望这对谁有帮助!

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

要做到这一点,显式地将它添加到每一行:

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

由于我们在这里已经很好地建立,writelines不会为您添加新行。但是,似乎每个人都错过了,是它不必当作一个直接的“对应物”时,为 readlines()和最初的阅读坚持换行!

When you open a file for reading in 二进制模式 (via 'rb'), then use readlines() to fetch the file contents into memory, split by line, the newlines remain attached to the end of your lines! So, if you then subsequently write them back, you don't likely want writelines to append anything!

So if, you do something like:

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

You should end up with the same file content you started with.

因为我们只想分隔行,而 python 中的 writelines函数不支持在行之间添加分隔符,所以我编写了下面这些最适合这个问题的简单代码:

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)

你就完了。

学分到 Brent Faust


Python > = 3.6使用格式字符串:

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

lines可以是 set

If you are oldschool (like me) you may add f.write('\n') below the second line.