Eu tenho o seguinte código:
import re
#open the xml file for reading:
file = open('path/test.xml','r+')
#convert to string:
data = file.read()
file.write(re.sub(r"<string>ABC</string>(\s+)<string>(.*)</string>",r"<xyz>ABC</xyz>\1<xyz>\2</xyz>",data))
file.close()
onde eu gostaria de substituir o conteúdo antigo que está no arquivo pelo novo conteúdo. Porém, quando eu executo meu código, o arquivo "test.xml" é anexado, ou seja, eu tenho o conteúdo antigo seguido pelo novo conteúdo "substituído". O que posso fazer para excluir as coisas antigas e apenas manter as novas?
data = file.read()
. Você não quer dizer "sobrescrever cegamente sem precisar lê-lo primeiro".Respostas:
Você precisa
seek
começar o arquivo antes de gravar e, em seguida, usarfile.truncate()
se quiser fazer a substituição no local:import re myfile = "path/test.xml" with open(myfile, "r+") as f: data = f.read() f.seek(0) f.write(re.sub(r"<string>ABC</string>(\s+)<string>(.*)</string>", r"<xyz>ABC</xyz>\1<xyz>\2</xyz>", data)) f.truncate()
A outra maneira é ler o arquivo e abri-lo novamente com
open(myfile, 'w')
:with open(myfile, "r") as f: data = f.read() with open(myfile, "w") as f: f.write(re.sub(r"<string>ABC</string>(\s+)<string>(.*)</string>", r"<xyz>ABC</xyz>\1<xyz>\2</xyz>", data))
Nem
truncate
nemopen(..., 'w')
vai mudar o inode número do arquivo (eu testei duas vezes, uma com o Ubuntu 12.04 NFS e uma vez com ext4).A propósito, isso não está realmente relacionado ao Python. O intérprete chama a API de baixo nível correspondente. O método
truncate()
funciona da mesma forma na linguagem de programação C: Veja http://man7.org/linux/man-pages/man2/truncate.2.htmlfonte
Neither truncate nor open(..., 'w') will change the inode number of the file
por que isso é importante?file='path/test.xml' with open(file, 'w') as filetowrite: filetowrite.write('new content')
Abra o arquivo no modo 'w', você poderá substituir o texto atual e salvar o arquivo por novos conteúdos.
fonte
Usando
truncate()
, a solução poderia serimport re #open the xml file for reading: with open('path/test.xml','r+') as f: #convert to string: data = f.read() f.seek(0) f.write(re.sub(r"<string>ABC</string>(\s+)<string>(.*)</string>",r"<xyz>ABC</xyz>\1<xyz>\2</xyz>",data)) f.truncate()
fonte
seek
etruncate
!!! Eu não conseguia descobrir por queseek
sozinho não estava funcionando.import os#must import this library if os.path.exists('TwitterDB.csv'): os.remove('TwitterDB.csv') #this deletes the file else: print("The file does not exist")#add this to prevent errors
Tive um problema semelhante e, em vez de substituir meu arquivo existente usando os diferentes 'modos', apenas excluí o arquivo antes de usá-lo novamente, de modo que seria como se estivesse anexando a um novo arquivo a cada execução de meu código .
fonte
Veja em Como Substituir String no Arquivo funciona de maneira simples e é uma resposta que funciona com
replace
fin = open("data.txt", "rt") fout = open("out.txt", "wt") for line in fin: fout.write(line.replace('pyton', 'python')) fin.close() fout.close()
fonte
Usando a biblioteca pathlib python3 :
import re from pathlib import Path import shutil shutil.copy2("/tmp/test.xml", "/tmp/test.xml.bak") # create backup filepath = Path("/tmp/test.xml") content = filepath.read_text() filepath.write_text(re.sub(r"<string>ABC</string>(\s+)<string>(.*)</string>",r"<xyz>ABC</xyz>\1<xyz>\2</xyz>", content))
Método semelhante usando uma abordagem diferente para backups:
from pathlib import Path filepath = Path("/tmp/test.xml") filepath.rename(filepath.with_suffix('.bak')) # different approach to backups content = filepath.read_text() filepath.write_text(re.sub(r"<string>ABC</string>(\s+)<string>(.*)</string>",r"<xyz>ABC</xyz>\1<xyz>\2</xyz>", content))
fonte