¿Forma correcta de escribir línea en archivo?


1069

Estoy acostumbrado a hacer print >>f, "hi there"

Sin embargo, parece que print >>está en desuso. ¿Cuál es la forma recomendada de hacer la línea de arriba?

Actualización : Respecto a todas esas respuestas con "\n"... ¿es universal o específico de Unix? IE, ¿debería estar haciendo "\r\n"en Windows?


11
"\ n" no es específico de Unix. Cuando el archivo se abre en modo de texto (predeterminado), se traduce automáticamente a la línea correcta que finaliza para la plataforma actual. Escribir "\ r \ n" produciría "\ r \ r \ n", lo cual está mal.
D Coetzee

Simplemente agregue la instrucción print ord (os.linesep) para ver el código ascii (10 en la mayoría de los sistemas UNIX)
Stefan Gruenwald

¿Por qué crees que está en desuso?
xxx ---

Respuestas:


1153

Esto debería ser tan simple como:

with open('somefile.txt', 'a') as the_file:
    the_file.write('Hello\n')

De la documentación:

No lo use os.linesepcomo terminador de línea cuando escriba archivos abiertos en modo texto (el valor predeterminado); use un solo '\ n' en su lugar, en todas las plataformas.

Algunas lecturas útiles:


37
Este ejemplo es mejor que el ejemplo de abrir / cerrar. Usar withes una forma más segura de recordar cerrar un archivo.
Eyal

18
No tengo que llamar the_file.close()?
Hussain


@Johnsyweb ¿Por qué dices "os.linesep. Hay muchas cosas buenas en os!", Cuando anteriormente en la publicación te recomendó no usarlo? Sospecho que hay una edición aquí, y podría ser la razón de los votos negativos.
Horse SMith

1
@ user3226167: Ese es un punto interesante. Pero, ¿por qué abrirías un archivo binario para escribir texto sin formato?
Johnsyweb

961

Debe usar la print()función que está disponible desde Python 2.6+

from __future__ import print_function  # Only needed for Python 2
print("hi there", file=f)

Para Python 3 no necesita import, ya que la print()función es la predeterminada.

La alternativa sería usar:

f = open('myfile', 'w')
f.write('hi there\n')  # python will convert \n to os.linesep
f.close()  # you can omit in most cases as the destructor will call it

Citando de la documentación de Python sobre nuevas líneas:

En la salida, si es de nueva línea Ninguno, ningún '\n'caracteres escritos se convierten a la línea de separación por defecto del sistema, os.linesep. Si la nueva línea es '', no se realiza ninguna traducción. Si la nueva línea es cualquiera de los otros valores legales, los '\n'caracteres escritos se traducen a la cadena dada.


35
-1 "Si quiere estar seguro, agregue os.linesep a la cadena en lugar de \n" require newline = "", de lo contrario obtendría \r\r\nen Windows. No hay ninguna razón para perder el tiempo con os.linesep.
John Machin

77
@Sorin: Su edición para agregar el modo de escritura es, por supuesto, una mejora. Sin embargo, extrañamente permanece intransigente sobre os.linesep. Mira mi respuesta. Por cierto, la documentación que cita es para 3.x, pero esta parte también es válida para 2.x en modo de texto: cualquier carácter '\ n' escrito se traduce al separador de línea predeterminado del sistema, os.linesep * . .. Windows: escribir os.linesep es lo mismo que escribir \r\nque contiene el \nque se traduce a os.linesep, que es \r\nel resultado final \r\r\n.
John Machin

77
@ John tenías razón, corregí el error os.linesep. Gracias.
Sorin

3
Para anexar ¿no es cierto open('myfile','a')en su lugar open('myfile','w')?
NeDark

66
@BradRuderman Eso es parte del estándar POSIX para lo que constituye una "línea" en un archivo de texto, es decir, cada línea en un archivo de texto debe terminar con una nueva línea, incluso la última línea.
Wheeler

116

Los documentos de Python recomiendan de esta manera:

with open('file_to_write', 'w') as f:
    f.write('file contents\n')

Entonces esta es la forma en que generalmente lo hago :)

Declaración de docs.python.org :

Es una buena práctica usar la palabra clave 'con' cuando se trata de objetos de archivo. Esto tiene la ventaja de que el archivo se cierra correctamente después de que finaliza su suite, incluso si se genera una excepción en el camino. También es mucho más corto que escribir bloques equivalentes try-finally.


1
No me gusta así cuando necesito anidar el withinterior de un bucle. Eso me hace abrir y cerrar constantemente el archivo a medida que avanzo en mi ciclo. ¿Quizás me estoy perdiendo algo aquí, o esto es realmente una desventaja en este escenario particular?
Sibbs Gambling

38
¿Qué hay de bucle dentro de la con?
j7nn7k

@ j7nn7k para línea en fd:
momstouch

86

En cuanto a os.linesep:

Aquí hay una sesión de intérprete Python 2.7.1 exacta sin editar en Windows:

Python 2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.linesep
'\r\n'
>>> f = open('myfile','w')
>>> f.write('hi there\n')
>>> f.write('hi there' + os.linesep) # same result as previous line ?????????
>>> f.close()
>>> open('myfile', 'rb').read()
'hi there\r\nhi there\r\r\n'
>>>

En Windows:

Como se esperaba, os.linesep NO produce el mismo resultado que '\n'. No hay forma de que pueda producir el mismo resultado. 'hi there' + os.linesepes equivalente a 'hi there\r\n', que NO es equivalente a 'hi there\n'.

Es así de simple: uso \nque se traducirá automáticamente a os.linesep. Y ha sido así de simple desde el primer puerto de Python a Windows.

No tiene sentido usar os.linesep en sistemas que no son de Windows, y produce resultados incorrectos en Windows.

¡NO USE os.linesep!


gran ejemplo: ¿tienes curiosidad si eres un usuario de ipython? buenas funciones para formatear sesiones
Alvin

No estoy completamente seguro de lo que intenta decirnos aquí. os.linesep devolverá el carácter de término de línea (o cadena) según lo definido por el sistema operativo. Windows usa \ r \ n para finales de línea de forma predeterminada. Sin embargo, se reconoce un solo \ n. Usar \ n dará una SALIDA totalmente portátil, pero os.linesep no está mal en Windows.
Gusdor

55
@Gusdor: El punto es que si usa explícitamente os.linesepen Windows en modo de texto, el resultado es el \r\r\nque está mal. "Windows usa ..." no tiene sentido. La biblioteca de tiempo de ejecución C (y por tanto Python) traducir \na \r\nen la salida en modo texto. Otro software puede comportarse de manera diferente. NO es el caso de que todo el software que se ejecuta en Windows reconozca un solitario \ncomo separador de línea cuando se lee en modo texto. Python lo hace. El editor de texto del Bloc de notas de Microsoft no.
John Machin

66
Podría decirse que alguien más lo leerá, no tú, con un software de mickey-mouse que se burlará del extra \r...
John Machin

2
@Gusdor, vienes a Python desde un idioma diferente, donde usar '\ n' da como resultado la salida de '\ n' en la ventana, en lugar de '\ r \ n', por lo que carece del '\ r' esperado por tonto editores de texto? Como dice John, no es así como se comporta Python: '\ n' se reemplaza automáticamente por '\ r \ n', si eso es lo que os.linesep dice que haga. Por lo tanto, decir explícitamente os.linesep es "incorrecto" aquí. Es como Department of Redundancy Department. Sí, tú puedes hacerlo. No, no quieres hacerlo.
ToolmakerSteve

55

No creo que haya una forma "correcta".

Yo usaría:

with open ('myfile', 'a') as f: f.write ('hi there\n')

En memoria de Tim Toady .


Pero el OP podría querer escribir cosas adicionales en el archivo. Aquí el archivo se cerrará cuando withsalga del alcance.
Keith

Eso podría querer ser open(..., 'a')o incluso 'at'.
mtrw

55
Erm, si. Esa es la idea de usar con. Si desea mantener abierto el archivo, simplemente abra abierto al principio y cierre cuando haya terminado ...
Hyperboreus

1
@mtrw. Cierto. OP estaba anexando.
Hyperboreus

1
En lo que respecta a Python, RIP Tim Toady, y muy, muy legítimamente
Mr_and_Mrs_D

21

En Python 3 es una función, pero en Python 2 puede agregar esto al principio del archivo fuente:

from __future__ import print_function

Entonces lo haces

print("hi there", file=f)

17

Si está escribiendo una gran cantidad de datos y la velocidad es una preocupación que probablemente debería seguir f.write(...). Hice una comparación de velocidad rápida y fue considerablemente más rápido que print(..., file=f)cuando realizaba una gran cantidad de escrituras.

import time    

start = start = time.time()
with open("test.txt", 'w') as f:
    for i in range(10000000):
        # print('This is a speed test', file=f)
        # f.write('This is a speed test\n')
end = time.time()
print(end - start)

En promedio, writeterminé en 2.45s en mi máquina, mientras que printtardó aproximadamente 4 veces más (9.76s). Dicho esto, en la mayoría de los escenarios del mundo real, esto no será un problema.

Si elige ir print(..., file=f), probablemente encontrará que querrá suprimir la nueva línea de vez en cuando, o reemplazarla por otra cosa. Esto puede hacerse configurando el endparámetro opcional , por ejemplo;

with open("test", 'w') as f:
    print('Foo1,', file=f, end='')
    print('Foo2,', file=f, end='')
    print('Foo3', file=f)

De cualquier forma que elija, le sugiero que use, withya que hace que el código sea mucho más fácil de leer.

Actualización : esta diferencia en el rendimiento se explica por el hecho de que writeestá altamente protegida y regresa antes de que se realicen las escrituras en el disco (vea esta respuesta ), mientras que print(probablemente) usa el almacenamiento en línea de la memoria intermedia. Una prueba simple para esto sería verificar el rendimiento de escrituras largas también, donde las desventajas (en términos de velocidad) para el almacenamiento en línea serían menos pronunciadas.

start = start = time.time()
long_line = 'This is a speed test' * 100
with open("test.txt", 'w') as f:
    for i in range(1000000):
        # print(long_line, file=f)
        # f.write(long_line + '\n')
end = time.time()

print(end - start, "s")

La diferencia de rendimiento ahora se vuelve mucho menos pronunciada, con un tiempo promedio de 2.20s para writey 3.10s para print. Si necesita concatenar un montón de cadenas para obtener este rendimiento de línea tan largo, sufrirá, por lo que los casos de uso donde printserían más eficientes son un poco raros.


10

Desde 3.5 también puede usar el pathlibpara ese propósito:

Path.write_text(data, encoding=None, errors=None)

Abra el archivo apuntado en modo texto, escriba datos en él y cierre el archivo:

import pathlib

pathlib.Path('textfile.txt').write_text('content')

5

Cuando dijo Línea, significa algunos caracteres serializados que terminan en '\ n' caracteres. La línea debe ser la última en algún punto, por lo que debemos considerar '\ n' al final de cada línea. Aquí hay solución:

with open('YOURFILE.txt', 'a') as the_file:
    the_file.write("Hello")

en el modo de agregar después de cada escritura, el cursor se mueve a una nueva línea, si desea usar el wmodo, debe agregar \ncaracteres al final de la write()función:

the_file.write("Hello\n")

1
"en modo de adición después de cada escritura, el cursor se mueve a una nueva línea" - no, no lo es.
Un

3

También se puede usar el iomódulo como en:

import io
my_string = "hi there"

with io.open("output_file.txt", mode='w', encoding='utf-8') as f:
    f.write(my_string)

1

Para escribir texto en un archivo en el matraz se puede usar:

filehandle = open("text.txt", "w")
filebuffer = ["hi","welcome","yes yes welcome"]
filehandle.writelines(filebuffer)
filehandle.close()

0

También puedes probar filewriter

pip install filewriter

from filewriter import Writer

Writer(filename='my_file', ext='txt') << ["row 1 hi there", "row 2"]

Escribe en my_file.txt

Toma un iterable o un objeto con __str__soporte.


0

Cuando necesito escribir muchas líneas nuevas, defino una lambda que usa una printfunción:

out = open(file_name, 'w')
fwl = lambda *x, **y: print(*x, **y, file=out) # FileWriteLine
fwl('Hi')

Este enfoque tiene la ventaja de que puede utilizar todas las funciones que están disponibles con la printfunción.

Actualización: como menciona Georgy en la sección de comentarios, es posible mejorar aún más esta idea con la partialfunción:

from functools import partial
fwl = partial(print, file=out)

En mi humilde opinión, este es un enfoque más funcional y menos críptico.


2
O de otra manera (probablemente más limpia) para escribir esto: from functools import partial; fwl = partial(print, file=out).
Georgy

@Georgy Su enfoque es tan bueno que se puede dar como una nueva respuesta.
MxNx

1
La idea es la misma que la suya, solo la implementación es un poco diferente. Si lo desea, puede agregarlo en una edición a su respuesta. Estoy bien con eso.
Georgy
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.