Writelines escribe líneas sin nueva línea, solo llena el archivo …

Tengo un progtwig que escribe una lista en un archivo. La lista es una lista de líneas delimitadas por tuberías y las líneas deben escribirse en el archivo de esta manera:

123|GSV|Weather_Mean|hello|joe|43.45 122|GEV|temp_Mean|hello|joe|23.45 124|GSI|Weather_Mean|hello|Mike|47.45 

PERO les escribió esta línea ahhhh:

 123|GSV|Weather_Mean|hello|joe|43.45122|GEV|temp_Mean|hello|joe|23.45124|GSI|Weather_Mean|hello|Mike|47.45 

Este progtwig escribió todas las líneas en una sola línea sin ningún tipo de saltos de línea … Esto me duele mucho y tengo que averiguar cómo revertir esto, pero de todos modos, ¿dónde está mal mi progtwig aquí? Pensé que las líneas de escritura deberían escribir líneas en el archivo en lugar de escribir todo en una sola línea …

 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) 

En realidad, este es un problema bastante común para los recién llegados a Python, especialmente porque, a través de la biblioteca estándar y las bibliotecas populares de terceros, algunas funciones de lectura eliminan las nuevas líneas, pero casi ninguna función de escritura (excepto las relacionadas con el log ) las agrega.

Entonces, hay un montón de código Python que hace cosas como:

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

o

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

Cualquiera de las dos es correcta y, por supuesto, incluso podría escribir su propia función de líneas de escritura con líneas nuevas que lo envuelva …

Pero solo debes hacer esto si no puedes evitarlo.

Es mejor si puede crear / mantener las nuevas líneas en primer lugar, como en las sugerencias de Greg Hewgill:

 line_list.append(new_line + "\n") 

Y es aún mejor si puede trabajar a un nivel más alto que las líneas de texto en bruto, por ejemplo, utilizando el módulo csv en la biblioteca estándar, como sugiere esuaro.

Por ejemplo, justo después de definir fw , puede hacer esto:

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

Entonces, en lugar de esto:

 new_line = d[looking_for]+'|'+'|'.join(columns[1:]) line_list.append(new_line) 

Tu hiciste esto:

 row_list.append(d[looking_for] + columns[1:]) 

Y al final, en lugar de esto:

 fw.writelines(line_list) 

Tu hiciste esto:

 cw.writerows(row_list) 

Finalmente, su diseño es “abrir un archivo, luego construir una lista de líneas para agregar al archivo, luego escribirlas todas a la vez”. Si vas a abrir el archivo en la parte superior, ¿por qué no solo escribes las líneas una por una? Ya sea que esté utilizando escrituras simples o un csv.writer , hará su vida más sencilla y su código más fácil de leer. (A veces puede haber razones de simplicidad, eficiencia o corrección para escribir un archivo de una sola vez, pero una vez que se ha open al extremo opuesto del progtwig desde la write , casi ha perdido algún beneficio) de todos a la vez.)

La documentación para writelines() establece:

writelines() no agrega separadores de línea

Así que tendrás que añadirlos tú mismo. Por ejemplo:

  line_list.append(new_line + "\n") 

cada vez que agregue un nuevo elemento a line_list .

writelines() no agrega separadores de línea. Puede alterar la lista de cadenas utilizando map() para agregar un nuevo \n (salto de línea) al final de cada cadena.

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

Como otros han señalado, writelines es un nombre inapropiado (ridículamente no agrega nuevas líneas al final de cada línea).

Para hacer eso, usa el mapa:

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

Como han mencionado otros, y en contra de lo que implicaría el nombre del método, las writelines no agregan separadores de línea. Este es un caso de libro de texto para un generador. Aquí hay un ejemplo artificial:

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

Beneficios: agrega nuevas líneas de forma explícita sin modificar los valores de entrada o salida ni realizar ninguna concatenación de cadenas desordenadas. Y, críticamente, no crea ninguna nueva estructura de datos en la memoria. IO (escribir en un archivo) es cuando ese tipo de cosas tienden a ser realmente importantes. ¡Espero que esto ayude a alguien!

Como bien hemos establecido aquí, writelines no agrega las nuevas líneas por usted. Pero, lo que todos parecen faltar, es que no es necesario cuando se usa como “contraparte” directa para readlines() y la lectura inicial perseveró en las nuevas líneas.

Cuando abre un archivo para leer en modo binario (a través de 'rb' ), luego use readlines() para obtener el contenido del archivo en la memoria, dividido por línea, ¡las nuevas líneas permanecen unidas al final de sus líneas! Por lo tanto, si luego los writelines no querrá añadir writelines de writelines .

Así que si, haces algo como:

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

Debería terminar con el mismo contenido de archivo con el que comenzó.

Seguí terminando en este hilo cuando buscaba resolver un problema similar cuando escribía en archivos en R. Entonces, para aquellos que han tenido el mismo problema, aquí está mi solución:

 List_To_Be_Written_To_File<-sprintf("%s%s",as.character(List_To_Be_Written_To_File),"\n")