我有一个程序将列表写入文件。 该列表是一个以管道分隔的行列表,这些行应该写入文件,如下所示:
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)
答案 0 :(得分:38)
对于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")
如果你可以在比原始文本行更高的层次上工作,例如,使用标准库中的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)
最后,你的设计是“打开一个文件,然后建立一个行列表添加到文件中,然后立即写入它们”。如果你要打开文件顶部,为什么不一个一个地写行?无论您使用简单的写入还是csv.writer
,它都会让您的生活变得更简单,并且您的代码更易于阅读。 (有时可能会有简单,高效或正确的理由一次性写入文件 - 但是一旦您将open
从write
一直移动到程序的另一端,你几乎失去了一次性的任何好处。)
答案 1 :(得分:35)
documentation for writelines()
州:
writelines()
不添加行分隔符
所以你需要自己添加它们。例如:
line_list.append(new_line + "\n")
每当您将新项目追加到line_list
时。
答案 2 :(得分:8)
writelines()
不添加行分隔符。您可以使用map()
在每个字符串的末尾添加新的\n
(换行符)来更改字符串列表。
items = ['abc', '123', '!@#']
items = map(lambda x: x + '\n', items)
w.writelines(items)
答案 3 :(得分:7)
正如其他人所指出的那样,writelines
是一个用词不当(它可笑地不会在每一行的末尾添加换行符。)
为此,请使用map:
with open(dst_filename, 'w') as f:
f.writelines(map(lambda s: s + '\n', lines))
答案 4 :(得分: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(写入文件)就是这种事情往往真正重要的事情。希望这有助于某人!
答案 5 :(得分:2)
归功于 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')
。
答案 6 :(得分:1)
由于我们只想分隔行,而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)
您已经完成。
答案 7 :(得分:0)
正如我们在此处已建立的,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)
您最终应该拥有与开始时相同的文件内容。
答案 8 :(得分:-2)
当我在写R中的文件时想要解决类似的问题时,我一直在这个帖子上结束。所以对于那些有同样问题的人来说,这是我的解决方案:
List_To_Be_Written_To_File<-sprintf("%s%s",as.character(List_To_Be_Written_To_File),"\n")