Lire et écraser un fichier en Python


108

J'utilise actuellement ceci:

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

Mais le problème est que l'ancien fichier est plus volumineux que le nouveau fichier. Je me retrouve donc avec un nouveau fichier qui contient une partie de l'ancien fichier à la fin.

Réponses:


178

Si vous ne souhaitez pas fermer et rouvrir le fichier, pour éviter les conditions de concurrence, vous pouvez 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 fonctionnalité sera probablement également plus propre et plus sûre en opentant que gestionnaire de contexte, ce qui fermera le gestionnaire de fichiers, même si une erreur se produit!

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

Juste pour être clair dans mon esprit - votre deuxième clip devrait-il avoir f.write(text)après f.truncate()?
volvox

2
@volvox f.write(text)est avant f.truncate()dans ce code; il écrit le textpremier, donc après que .write()le curseur de fichier soit positionné à la fin de text. Le fait de tronquer le fichier supprimera tous les octets restants que le fichier pourrait avoir après ce point. Dans ce cas, le résultat final serait le même que si vous aviez tronqué avant d'écrire.
nosklo

Pour les fichiers très volumineux, la lecture de l'intégralité du contenu du fichier en mémoire peut devenir compliquée. Par conséquent, le fileinputmodule peut devenir la méthode préférée. Une fois passé inplace=1, il déplacera d'abord le fichier vers un emplacement temporaire, puis écrira un nouveau fichier dans l'ancien chemin du nom de fichier. Cette opération de déplacement est rapide sur les systèmes de fichiers Unix, car elle ne fait que déplacer le système de fichiers inode, pas le contenu complet. Ensuite, vous pouvez lire et traiter chaque ligne individuellement pour éviter le gonflement de la mémoire. :-)
TrinitronX

16

Il serait probablement plus facile et plus propre de fermer le fichier après text = re.sub('foobar', 'bar', text), de le rouvrir pour l'écriture (effaçant ainsi l'ancien contenu) et d'y écrire votre texte mis à jour.


16

Le fileinputmodule a un inlinemode pour écrire les changements dans le fichier que vous traitez sans utiliser de fichiers temporaires, etc. numéro de ligne, etc. si vous voulez les inspecter à l'intérieur de la boucle.

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

0

Honnêtement, vous pouvez jeter un œil à cette classe que j'ai construite et qui effectue des opérations de base sur les fichiers. La méthode write écrase et ajoute conserve les anciennes données.

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

Essayez de l'écrire dans un nouveau fichier.

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()
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.