2010-04-20 17 views
18

Lo estoy haciendo así ahora, pero quiero que escriba al principio del archivo.write() al principio del archivo?

f = open('out.txt', 'a') # or 'w'? 
f.write("string 1") 
f.write("string 2") 
f.write("string 3") 
f.close() 

por lo que el contenido de out.txt serán:

string 3 
string 2 
string 1 

y no (como el código hace):

string 1 
string 2 
string 3 

Respuesta

12

Eche un vistazo a this question. Hay algunas soluciones allí.

Aunque probablemente volvería misma manera que Daniel y MAK sugieren - tal vez hacer una clase lil' hacer las cosas un poco más flexible y explícito:

class Prepender: 

    def __init__(self, fname, mode='w'): 
     self.__write_queue = [] 
     self.__f = open(fname, mode) 

    def write(self, s): 
     self.__write_queue.insert(0, s) 

    def close(self): 
     self.__exit__(None, None, None) 

    def __enter__(self): 
     return self 

    def __exit__(self, type, value, traceback): 
     if self.__write_queue: 
      self.__f.writelines(self.__write_queue) 
     self.__f.close() 

with Prepender('test_d.out') as f: 
    f.write('string 1\n') 
    f.write('string 2\n') 
    f.write('string 3\n') 
7

que podría lanzar un f.seek(0) entre cada escritura (o escribir una función de envoltura que lo hace por usted), pero no hay una forma sencilla de hacerlo.

EDIT: esto no funciona, incluso si pone un f.flush() allí se sobrescribirá continuamente. Puede que tenga que poner en cola las escrituras y revertir el pedido usted mismo.

Así que en lugar de

f.write("string 1") 
f.write("string 2") 
f.write("string 3") 

tal vez hacer algo como:

writeList = [] 
writeList.append("string 1\n") 
writeList.append("string 2\n") 
writeList.append("string 3\n") 
writeList.reverse() 
f.writelines(writeList) 
1

Abundando en la respuesta de Daniel DiPaolo:

Simplemente añada todas las líneas que desea escribir en un list. Invierta el list y luego escriba su contenido en el archivo.

f=open('output.txt','w') 

l=[] 
l.append("string 1") 
l.append("string 2") 
l.append("string 3") 

for line in l: 
    f.write(line) 

f.close() 

También es posible usar un deque y añadir líneas en su principio en lugar de utilizar un list y darle la vuelta.

+0

¿Qué pasa si el uso de este era más como un archivo de registro, donde la secuencia de comandos puede escribir en el registro de las ejecuciones sucesivas? ¿Es el único recurso para mantener todo el archivo en la memoria, buscar al principio para escribir sus cosas seguido de todos los contenidos anteriores? (excluyendo la creación de archivos intermedios) –

+0

No conozco nada en la clase 'file' de Python que permita algo como esto directamente (es decir, sin utilizar algún tipo de buffer intermedio). Entonces, en este momento, esto parece ser la forma más simple. Para un archivo de registro, ¿no tendría mucho más sentido y simplificaría la vida simplemente al agregar las entradas más nuevas al final del archivo? – MAK

+0

@Nick, @MAK, no solo no hay nada en Python que pueda manejar esto, no hay nada en la biblioteca C subyacente o en el sistema de archivos. Esto simplemente no es cómo funcionan los archivos, y no se puede hacer crecer un archivo más que añadiendo a menos que esté dispuesto a copiar el contenido. Podría hacerse con un nuevo archivo o moviendo datos dentro del archivo anterior, pero de todos modos es muy probable que sea una mala idea. Mejor cambiar los requisitos o la forma en que ves el problema ... –

1

Una variación en la respuesta de kdtrv. Esta versión mantiene el contenido del archivo existente y ofrece un método write_lines que preserva el orden de la línea.

class Prepender(object): 
    def __init__(self, 
       file_path, 
       ): 
     # Read in the existing file, so we can write it back later 
     with open(file_path, mode='r') as f: 
      self.__write_queue = f.readlines() 

     self.__open_file = open(file_path, mode='w') 

    def write_line(self, line): 
     self.__write_queue.insert(0, 
            "%s\n" % line, 
           ) 

    def write_lines(self, lines): 
     lines.reverse() 
     for line in lines: 
      self.write_line(line) 

    def close(self): 
     self.__exit__(None, None, None) 

    def __enter__(self): 
     return self 

    def __exit__(self, type, value, traceback): 
     if self.__write_queue: 
      self.__open_file.writelines(self.__write_queue) 
     self.__open_file.close() 


with Prepender('test_d.out') as f: 
    # Must write individual lines in reverse order 
    f.write_line('This will be line 3') 
    f.write_line('This will be line 2') 
    f.write_line('This will be line 1') 

with Prepender('test_d.out') as f: 
    # Or, use write_lines instead - that maintains order. 
    f.write_lines(
     ['This will be line 1', 
     'This will be line 2', 
     'This will be line 3', 
     ] 
    ) 
Cuestiones relacionadas