2010-04-20 12 views
18

Ora lo sto facendo in questo modo, ma voglio che scriva all'inizio del file.write() all'inizio del file?

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

in modo che il contenuto di out.txt saranno:

string 3 
string 2 
string 1 

e non (come questo codice fa):

string 1 
string 2 
string 3 

risposta

12

Dai uno sguardo allo this question. Ci sono alcune soluzioni lì.

Anche se avrei probabilmente andare in quel stesso modo Daniele e MAK suggeriscono - magari fare una 'classe lil per rendere le cose un po' più flessibile ed esplicito:

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

Si potrebbe gettare un f.seek(0) tra ogni scrittura (o scrivere una funzione wrapper che fa per te), ma non c'è un modo semplice per farlo.

EDIT: questo non funziona, anche se si inserisce uno f.flush() in esso verrà continuamente sovrascritto. Dovresti semplicemente mettere in coda le scritture e invertire l'ordine da solo.

Così, invece di

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

forse fare qualcosa di simile:

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

Elaborando risposta di Daniel DiPaolo:

Basta aggiungere tutti le linee che si desidera scrivere a un list. Invertire il list e quindi scrivere il suo contenuto nel file.

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

Si potrebbe anche usare un deque e aggiungere linee al suo inizio invece di utilizzare un list e invertire la tendenza.

+0

E se l'utilizzo fosse più simile a un file di registro, in cui lo script potrebbe scrivere sul registro delle esecuzioni successive? È l'unica risorsa per tenere in memoria l'intero file, cercare all'inizio di scrivere le tue cose seguite da tutti i contenuti precedenti? (esclusa la creazione di file intermedi) –

+0

Non sono a conoscenza di qualcosa nella classe 'file' di Python che consente qualcosa di simile direttamente (cioè senza utilizzare una sorta di buffer intermedio). Quindi, al momento, questo sembra il modo più semplice. Per un file di log, non avrebbe molto più senso e rendere la vita molto più semplice semplicemente aggiungere le voci più recenti alla fine del file? – MAK

+0

@Nick, @MAK, non solo non c'è nulla in Python in grado di gestirlo, non c'è nulla nella libreria C sottostante o nel filesystem. Questo non è semplicemente il modo in cui i file funzionano e non è possibile far crescere un file se non aggiungendolo a meno che non siate disposti a copiare il contenuto. Potrebbe essere fatto con un nuovo file o spostando i dati all'interno del vecchio file, ma in entrambi i casi è molto probabilmente una cattiva idea. Meglio cambiare i requisiti o il modo in cui visualizzi il problema ... –

1

Una variante di risposta di kdtrv. Questa versione mantiene il contenuto del file esistente e offre un metodo write_lines che conserva l'ordine delle righe.

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', 
     ] 
    )