我有一个程序将列表写入文件.该列表是管道分隔的行列表,应该将这些行写入文件,如下所示:
123|GSV|Weather_Mean|hello|joe|43.45
122|GEV|temp_Mean|hello|joe|23.45
124|GSI|Weather_Mean|hello|Mike|47.45
Run Code Online (Sandbox Code Playgroud)
但它写了这行啊啊啊:
123|GSV|Weather_Mean|hello|joe|43.45122|GEV|temp_Mean|hello|joe|23.45124|GSI|Weather_Mean|hello|Mike|47.45
Run Code Online (Sandbox Code Playgroud)
这个程序把所有的行都写成了一行,没有任何换行符.这给我带来了很大的麻烦,我想弄清楚如何扭转这一点,但无论如何,我的程序错在哪里?我认为写行应该在文件中写下行而不是只写一行到一行.
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)
Run Code Online (Sandbox Code Playgroud)
aba*_*ert 43
这对于Python的新手来说实际上是一个非常普遍的问题 - 特别是因为在标准库和流行的第三方库中,一些读取函数会删除换行符,但几乎没有写入函数(除了log相关的东西)添加它们.
所以,有很多Python代码可以执行以下操作:
fw.write('\n'.join(line_list) + '\n')
Run Code Online (Sandbox Code Playgroud)
要么
fw.write(line + '\n' for line in line_list)
Run Code Online (Sandbox Code Playgroud)
任何一个都是正确的,当然你甚至可以编写自己的writelinesWithNewlines函数来包装它...
但是,如果你无法避免,那么你应该这样做.
如果您可以创建/保留换行符,那就更好了 - 正如Greg Hewgill的建议:
line_list.append(new_line + "\n")
Run Code Online (Sandbox Code Playgroud)
如果你可以在比原始文本行更高的层次上工作,例如,使用标准库中的csv模块,就像esuaro所说的那样,它会更好.
例如,在定义之后fw,您可能会这样做:
cw = csv.writer(fw, delimiter='|')
Run Code Online (Sandbox Code Playgroud)
然后,而不是这个:
new_line = d[looking_for]+'|'+'|'.join(columns[1:])
line_list.append(new_line)
Run Code Online (Sandbox Code Playgroud)
你做这个:
row_list.append(d[looking_for] + columns[1:])
Run Code Online (Sandbox Code Playgroud)
最后,而不是这个:
fw.writelines(line_list)
Run Code Online (Sandbox Code Playgroud)
你做这个:
cw.writerows(row_list)
Run Code Online (Sandbox Code Playgroud)
最后,您的设计是"打开一个文件,然后构建一个行列表以添加到文件中,然后立即将它们全部写入".如果你要打开文件顶部,为什么不一个一个地写行?无论您是使用简单的写入还是使用简单的写入csv.writer,它都会让您的生活变得更简单,并且您的代码更易于阅读.(有时可能会有简单,高效或正确的理由一次性写入一个文件 - 但是一旦你将open所有文件一直移动到程序的另一端write,你几乎失去了所有的好处特技的一次.)
Gre*_*ill 40
各州的文件writelines():
writelines()不添加行分隔符
所以你需要自己添加它们.例如:
line_list.append(new_line + "\n")
Run Code Online (Sandbox Code Playgroud)
每当你追加一个新项目line_list.
Bre*_*ust 11
正如其他人所指出的那样,writelines是用词不当(它可笑地不会在每一行的末尾添加换行符).
为此,请使用map:
with open(dst_filename, 'w') as f:
f.writelines(s + '\n' for s in lines)
Run Code Online (Sandbox Code Playgroud)
qrä*_*bnö 11
致谢Brent Faust。
Python >= 3.6,带格式字符串:
with open(dst_filename, 'w') as f:
f.writelines(f'{s}\n' for s in lines)
Run Code Online (Sandbox Code Playgroud)
lines可以是一个set.
如果您是老派(像我一样),您可以在f.write('\n')第二行下方添加。
writelines()不添加行分隔符.您可以通过在每个字符串的末尾map()添加新的\n(换行符)来更改字符串列表.
items = ['abc', '123', '!@#']
items = map(lambda x: x + '\n', items)
w.writelines(items)
Run Code Online (Sandbox Code Playgroud)
正如其他人所提到的,与方法名称所暗示的相反,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))
Run Code Online (Sandbox Code Playgroud)
优点:显式添加换行符,无需修改输入或输出值或进行任何混乱的字符串连接。而且,最重要的是,不会在内存中创建任何新的数据结构。IO(写入文件)是这类事情真正重要的时候。希望这对某人有帮助!