web-dev-qa-db-fra.com

Modification d’une ligne spécifique dans un fichier texte dans Python

Disons que j'ai un fichier texte contenant:

Dan
Warrior
500
1
0

Est-il possible de modifier une ligne spécifique dans ce fichier texte? En ce moment j'ai ceci:

#!/usr/bin/env python
import io

myfile = open('stats.txt', 'r')
dan = myfile.readline()
print dan
print "Your name: " + dan.split('\n')[0]

try:
    myfile = open('stats.txt', 'a')
    myfile.writelines('Mage')[1]
except IOError:
        myfile.close()
finally:
        myfile.close()

Oui, je sais que myfile.writelines('Mage')[1] est incorrect. Mais vous obtenez mon point, non? J'essaie de modifier la ligne 2 en remplaçant Warrior par Mage. Mais puis-je même faire ça?

61
test

Vous voulez faire quelque chose comme ça:

# with is like your try .. finally block in this case
with open('stats.txt', 'r') as file:
    # read a list of lines into data
    data = file.readlines()

print data
print "Your name: " + data[0]

# now change the 2nd line, note that you have to add a newline
data[1] = 'Mage\n'

# and write everything back
with open('stats.txt', 'w') as file:
    file.writelines( data )

La raison en est que vous ne pouvez pas faire quelque chose comme "modifier la ligne 2" directement dans un fichier. Vous pouvez uniquement écraser (et non supprimer) des parties d'un fichier, ce qui signifie que le nouveau contenu ne couvre que l'ancien contenu. Donc, si vous écrivez "Mage" sur la ligne 2, la ligne résultante sera "Mageior".

85
Jochen Ritzel

vous pouvez utiliser fileinput pour faire de la modification sur place

import fileinput
for  line in fileinput.FileInput("myfile", inplace=1):
    if line .....:
         print line
18
ghostdog74
def replace_line(file_name, line_num, text):
    lines = open(file_name, 'r').readlines()
    lines[line_num] = text
    out = open(file_name, 'w')
    out.writelines(lines)
    out.close()

Et alors:

replace_line('stats.txt', 0, 'Mage')
16
Peter C

Si votre texte ne contient qu'un seul individu:

import re

# creation
with open('pers.txt','wb') as g:
    g.write('Dan \n Warrior \n 500 \r\n 1 \r 0 ')

with open('pers.txt','rb') as h:
    print 'exact content of pers.txt before treatment:\n',repr(h.read())
with open('pers.txt','rU') as h:
    print '\nrU-display of pers.txt before treatment:\n',h.read()


# treatment
def roplo(file_name,what):
    patR = re.compile('^([^\r\n]+[\r\n]+)[^\r\n]+')
    with open(file_name,'rb+') as f:
        ch = f.read()
        f.seek(0)
        f.write(patR.sub('\\1'+what,ch))
roplo('pers.txt','Mage')


# after treatment
with open('pers.txt','rb') as h:
    print '\nexact content of pers.txt after treatment:\n',repr(h.read())
with open('pers.txt','rU') as h:
    print '\nrU-display of pers.txt after treatment:\n',h.read()

Si votre texte contient plusieurs individus:

import re

# creation
with open('pers.txt','wb') as g:
    g.write('Dan \n Warrior \n 500 \r\n 1 \r 0 \n Jim  \n  dragonfly\r300\r2\n10\r\nSomo\ncosmonaut\n490\r\n3\r65')

with open('pers.txt','rb') as h:
    print 'exact content of pers.txt before treatment:\n',repr(h.read())
with open('pers.txt','rU') as h:
    print '\nrU-display of pers.txt before treatment:\n',h.read()


# treatment
def ripli(file_name,who,what):
    with open(file_name,'rb+') as f:
        ch = f.read()
        x,y = re.search('^\s*'+who+'\s*[\r\n]+([^\r\n]+)',ch,re.MULTILINE).span(1)
        f.seek(x)
        f.write(what+ch[y:])
ripli('pers.txt','Jim','Wizard')


# after treatment
with open('pers.txt','rb') as h:
    print 'exact content of pers.txt after treatment:\n',repr(h.read())
with open('pers.txt','rU') as h:
    print '\nrU-display of pers.txt after treatment:\n',h.read()

Si le "travail" d’un individu a une longueur constante dans le texte, vous ne pouvez modifier que la partie du texte correspondant au "travail" de l’individu souhaité: c’est la même idée que celle de senderle.

Mais selon moi, il serait préférable de mettre les caractéristiques des individus dans un dictionnaire enregistré dans un fichier avec cPickle:

from cPickle import dump, load

with open('cards','wb') as f:
    dump({'Dan':['Warrior',500,1,0],'Jim':['dragonfly',300,2,10],'Somo':['cosmonaut',490,3,65]},f)

with open('cards','rb') as g:
    id_cards = load(g)
print 'id_cards before change==',id_cards

id_cards['Jim'][0] = 'Wizard'

with open('cards','w') as h:
    dump(id_cards,h)

with open('cards') as e:
    id_cards = load(e)
print '\nid_cards after change==',id_cards
3
eyquem

Vous pouvez le faire de deux manières, choisissez ce qui convient à vos besoins:

Méthode I.) Remplacement par le numéro de ligne. Vous pouvez utiliser la fonction intégrée enumerate() dans ce cas:

Tout d'abord, en mode lecture récupère toutes les données d'une variable

with open("your_file.txt",'r') as f:
    get_all=f.readlines()

Deuxièmement, écrivez dans le fichier (où énumérer vient à l'action)

with open("your_file.txt",'w') as f:
    for i,line in enumerate(get_all,1):         ## STARTS THE NUMBERING FROM 1 (by default it begins with 0)    
        if i == 2:                              ## OVERWRITES line:2
            f.writelines("Mage\n")
        else:
            f.writelines(line)

Méthode II.) En utilisant le mot-clé que vous voulez remplacer:

Ouvrir le fichier en mode en lecture et copier le contenu dans une liste

with open("some_file.txt","r") as f:
    newline=[]
    for Word in f.readlines():        
        newline.append(Word.replace("Warrior","Mage"))  ## Replace the keyword while you copy.  

"Warrior" a été remplacé par "Mage", écrivez donc les données mises à jour dans le fichier:

with open("some_file.txt","w") as f:
    for line in newline:
        f.writelines(line)

Voici ce que sortie sera dans les deux cas:

Dan                   Dan           
Warrior   ------>     Mage       
500                   500           
1                     1   
0                     0           
2
Aseem Yadav

Je me suis entraîné à travailler sur des fichiers ce soir et je me suis rendu compte que je pouvais me baser sur la réponse de Jochen pour fournir une plus grande fonctionnalité pour un usage répété/multiple. Malheureusement, ma réponse n'aborde pas le problème du traitement des fichiers volumineux, mais facilite la vie dans les fichiers plus petits.

with open('filetochange.txt', 'r+') as foo:
    data = foo.readlines()                  #reads file as list
    pos = int(input("Which position in list to edit? "))-1  #list position to edit
    data.insert(pos, "more foo"+"\n")           #inserts before item to edit
    x = data[pos+1]
    data.remove(x)                      #removes item to edit
    foo.seek(0)                     #seeks beginning of file
    for i in data:
        i.strip()                   #strips "\n" from list items
        foo.write(str(i))
2
theYnot