web-dev-qa-db-fra.com

Ajouter une ligne à un fichier existant en Python

J'ai besoin d'ajouter une seule ligne à la première ligne d'un fichier texte et il semble que les seules options disponibles soient davantage de lignes de code que celles que j'attendrais de Python. Quelque chose comme ça:

f = open('filename','r')
temp = f.read()
f.close()

f = open('filename', 'w')
f.write("#testfirstline")

f.write(temp)
f.close()

N'y a-t-il pas de moyen plus facile? De plus, je vois plus souvent cet exemple à deux poignées que l'ouverture d'une seule poignée pour la lecture et l'écriture ('r +'). Pourquoi?

51
Nick

Python facilite beaucoup de choses et contient des bibliothèques et des wrappers pour de nombreuses opérations courantes, mais l'objectif n'est pas de cacher des vérités fondamentales.

La vérité fondamentale que vous rencontrez ici est que vous ne pouvez généralement pas ajouter de données à une structure plate existante sans réécrire la structure entière. Ceci est vrai quelle que soit la langue.

Il existe différentes manières de sauvegarder un descriptif de fichier ou de rendre votre code moins lisible. La plupart d'entre elles sont fournies dans d'autres réponses, mais aucune ne modifie l'opération fondamentale: vous devez lire le fichier existant, puis écrire les données que vous souhaitez ajouter, suivies de les données existantes que vous avez lues.

Économisez certainement le descripteur de fichier, mais ne cherchez pas à compresser cette opération dans le moins de lignes de code possible. En fait, ne cherchez jamais le moins de lignes de code possible - c'est de l'obscurcissement, pas de la programmation.

72
Nicholas Knight

Je me contenterais de lire et d’écrire séparément, mais nous pouvons certainement les exprimer de manière plus concise:

Python2:

with file('filename', 'r') as original: data = original.read()
with file('filename', 'w') as modified: modified.write("new first line\n" + data)

Python3: 

with open('filename', 'r') as original: data = original.read()
with open('filename', 'w') as modified: modified.write("new first line\n" + data)

Remarque: la fonction file () n'est pas disponible dans python3.

42
Karl Knechtel

Autre approche:

with open("infile") as f1:
    with open("outfile", "w") as f2:
        f2.write("#test firstline")
        for line in f1:
            f2.write(line)

ou un one liner:

open("outfile", "w").write("#test firstline\n" + open("infile").read())

Merci de m'avoir donné l'occasion de réfléchir à ce problème :)

À votre santé

20
Morlock
with open("file", "r+") as f: s = f.read(); f.seek(0); f.write("prepend\n" + s)
7
barti_ddu

Vous pouvez enregistrer un appel en écriture avec ceci:

f.write('#testfirstline\n' + temp)

Lorsque vous utilisez 'r +', vous devez rembobiner le fichier après l'avoir lu et avant de l'avoir écrit.

3
infrared

Voici un 3 lignes qui, à mon avis, est clair et flexible. Il utilise la fonction list.insert, donc si vous voulez vraiment ajouter le fichier au début, utilisez l.insert (0, 'insert_str'). Quand je l'ai fait pour un module Python que je développe, j'ai utilisé l.insert (1, 'insert_str') parce que je voulais ignorer la chaîne de caractères '# - -: uf-8 - -' à la ligne 0. Voici le code.

f = open(file_path, 'r'); s = f.read(); f.close()
l = s.splitlines(); l.insert(0, 'insert_str'); s = '\n'.join(l)
f = open(file_path, 'w'); f.write(s); f.close()

Cela fait le travail sans lire le fichier entier en mémoire, bien que cela puisse ne pas fonctionner sous Windows

def prepend_line(path, line):
    with open(path, 'r') as old:
        os.unlink(path)
        with open(path, 'w') as new:
            new.write(str(line) + "\n")
            shutil.copyfileobj(old, new)
2
eug

Une possibilité est la suivante:

import os
open('tempfile', 'w').write('#testfirstline\n' + open('filename', 'r').read())
os.rename('tempfile', 'filename')
0
JooMing

Est-ce que je ne vois pas quelque chose ou ne pourrions-nous pas simplement utiliser un tampon assez grand pour lire le fichier d'entrée en plusieurs parties (au lieu du contenu entier ) et avec ce tampon traverser le fichier tant qu'il est ouvert et continuer à échanger le fichier <-> le contenu du tampon?

Cela semble beaucoup plus efficace (surtout pour les gros fichiers) que de lire le contenu entier en mémoire , le modifier en mémoire et l'écrire dans le même fichier ou (pire encore) dans un autre . Désolé que maintenant je n'ai pas le temps d'implémenter un extrait de code, j'y reviendrai plus tard, mais vous avez peut-être une idée.

0
Corneliu Zuzu

Si vous souhaitez ajouter un fichier après un texte spécifique, vous pouvez utiliser la fonction ci-dessous.

def prepend_text(file, text, after=None):
    ''' Prepend file with given raw text '''
    f_read = open(file, 'r')
    buff = f_read.read()
    f_read.close()
    f_write = open(file, 'w')
    inject_pos = 0
    if after:
        pattern = after
        inject_pos = buff.find(pattern)+len(pattern)
    f_write.write(buff[:inject_pos] + text + buff[inject_pos:])
    f_write.close()

Donc, vous devez d'abord ouvrir le fichier, le lire et le sauvegarder dans une chaîne ..__ Ensuite, nous essayons de trouver le numéro du caractère dans la chaîne où l'injection aura lieu. Ensuite, avec une seule écriture et une indexation intelligente de la chaîne, nous pouvons maintenant réécrire tout le fichier, y compris le texte injecté.

0
Pithikos