Leggi e sovrascrivi un file in Python


108

Attualmente sto usando questo:

f = open(filename, 'r+')
text = f.read()
text = re.sub('foobar', 'bar', text)
f.seek(0)
f.write(text)
f.close()

Ma il problema è che il vecchio file è più grande del nuovo file. Quindi finisco con un nuovo file che ha una parte del vecchio file alla fine di esso.

Risposte:


178

Se non vuoi chiudere e riaprire il file, per evitare condizioni di gara, potresti truncate:

f = open(filename, 'r+')
text = f.read()
text = re.sub('foobar', 'bar', text)
f.seek(0)
f.write(text)
f.truncate()
f.close()

La funzionalità sarà probabilmente anche più pulita e sicura utilizzando opencome gestore di contesto, che chiuderà il gestore di file, anche se si verifica un errore!

with open(filename, 'r+') as f:
    text = f.read()
    text = re.sub('foobar', 'bar', text)
    f.seek(0)
    f.write(text)
    f.truncate()

Giusto per essere chiaro nella mia mente: la tua seconda clip dovrebbe avere f.write(text)dopo f.truncate()?
volvox

2
@volvox f.write(text)è prima f.truncate()in questo codice; scrive il textprimo, quindi dopo che .write()il cursore del file è posizionato alla fine di text. Il processo di troncamento del file rimuoverà tutti i byte rimanenti che il file potrebbe avere dopo questo punto. In questo caso, il risultato finale sarebbe lo stesso di se avessi troncato prima di scrivere.
nosklo

Per file molto grandi, la lettura dell'intero contenuto del file in memoria può diventare ingombrante. Pertanto, il fileinputmodulo può diventare il metodo preferito. Una volta passato inplace=1, sposterà prima il file in una posizione temporanea, quindi scriverà un nuovo file nel vecchio percorso del nome file. Questa operazione di spostamento è veloce sui filesystem unix, perché sposta solo il filesystem inode, non l'intero contenuto. Quindi puoi leggere ed elaborare ogni riga individualmente per evitare il gonfiore della memoria. :-)
TrinitronX

16

Probabilmente sarebbe più facile e più ordinato chiudere il file dopo text = re.sub('foobar', 'bar', text), riaprirlo per la scrittura (cancellando così i vecchi contenuti) e scrivervi il testo aggiornato.


16

Il fileinputmodulo ha una inlinemodalità per scrivere le modifiche al file che stai elaborando senza usare file temporanei, ecc. Il modulo incapsula bene l'operazione comune di scorrere le righe in un elenco di file, tramite un oggetto che tiene traccia in modo trasparente del nome del file, numero di riga ecc. se si desidera ispezionarli all'interno del ciclo.

import fileinput
for line in fileinput.FileInput("file",inplace=1):
    if "foobar" in line:
         line=line.replace("foobar","bar")
    print line

0

Onestamente puoi dare un'occhiata a questa classe che ho creato che fa operazioni di base sui file. Il metodo di scrittura sovrascrive e accoda mantiene i vecchi dati.

class IO:
    def read(self, filename):
        toRead = open(filename, "rb")

        out = toRead.read()
        toRead.close()
        
        return out
    
    def write(self, filename, data):
        toWrite = open(filename, "wb")

        out = toWrite.write(data)
        toWrite.close()

    def append(self, filename, data):
        append = self.read(filename)
        self.write(filename, append+data)
        

-2

Prova a scriverlo in un nuovo file ..

f = open(filename, 'r+')
f2= open(filename2,'a+')
text = f.read()
text = re.sub('foobar', 'bar', text)
f.seek(0)
f.close()
f2.write(text)
fw.close()
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.