Writelines пишет строки без перевода строки, просто заполняет файл
У меня есть программа, которая записывает список в файл.
Список - это список строк с разделителями каналов, и строки должны быть записаны в файл следующим образом:
123|GSV|Weather_Mean|hello|joe|43.45
122|GEV|temp_Mean|hello|joe|23.45
124|GSI|Weather_Mean|hello|Mike|47.45
НО он написал им строку this ahhhh:
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 = "[email protected]"
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)
Ответы
Ответ 1
Это на самом деле довольно распространенная проблема для новичков в Python, особенно потому, что через стандартную библиотеку и популярные сторонние библиотеки некоторые функции чтения вычеркивают символы новой строки, но почти не имеют функций записи (кроме связанных с log
) добавьте их.
Итак, там много кода Python, который делает такие вещи, как:
fw.write('\n'.join(line_list) + '\n')
или
fw.write(line + '\n' for line in line_list)
Либо один правильный, и, конечно, вы даже можете написать свои собственные сценарии с функциейNewlines, которая завершает его...
Но вы должны делать это только в том случае, если не можете этого избежать.
Лучше, если вы можете создать/сохранить новые строки в первую очередь - как в предложениях Грега Хьюглилла:
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
, вы довольно многое потеряло все преимущества "все-в-одном".)
Ответ 2
Документация для writelines()
гласит:
writelines()
не добавляет разделители строк
Итак, вам нужно добавить их самостоятельно. Например:
line_list.append(new_line + "\n")
всякий раз, когда вы добавляете новый элемент в line_list
.
Ответ 3
writelines()
не добавляет разделителей строк. Вы можете изменить список строк, используя map()
, чтобы добавить новый \n
(разрыв строки) в конце каждой строки.
items = ['abc', '123', '[email protected]#']
items = map(lambda x: x + '\n', items)
w.writelines(items)
Ответ 4
Как уже отмечали другие, writelines
- это неправильно (это нелепо не добавляет новые строки в конце каждой строки).
Для этого используйте карту:
with open(dst_filename, 'w') as f:
f.writelines(map(lambda s: s + '\n', lines))
Ответ 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 (запись в файл) - это когда такая вещь имеет значение. Надеюсь, это поможет кому-то!
Ответ 6
Как мы здесь хорошо зарекомендовали себя, writelines
не добавляет 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)
Вы должны получить тот же самый файл, с которым вы начали.
Ответ 7
Я продолжал заканчивать эту тему, когда искал решение подобной проблемы при записи файлов в R. Итак, для тех, у кого была такая же проблема, вот мое решение:
List_To_Be_Written_To_File<-sprintf("%s%s",as.character(List_To_Be_Written_To_File),"\n")