Mam następujący kod:
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()
gdzie chciałbym zastąpić starą zawartość znajdującą się w pliku nową zawartością. Jednak gdy wykonuję kod, dołączany jest plik „test.xml”, tzn. Mam starą zawartość za nową zawartością „zastąpioną”. Co mogę zrobić, aby usunąć stare rzeczy i zachować tylko nowe?
data = file.read()
. Nie masz na myśli „ślepego nadpisania bez konieczności wcześniejszego przeczytania”.Odpowiedzi:
Musisz
seek
zacząć plik przed zapisaniem, a następnie użyć,file.truncate()
jeśli chcesz wykonać zamianę w miejscu: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()
Innym sposobem jest odczytanie pliku, a następnie ponowne otwarcie go za pomocą
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))
Ani
truncate
teżopen(..., 'w')
nie zmieni numeru i- węzła pliku (testowałem dwukrotnie, raz z Ubuntu 12.04 NFS i raz z ext4).Nawiasem mówiąc, nie jest to tak naprawdę związane z Pythonem. Interpreter wywołuje odpowiedni interfejs API niskiego poziomu. Metoda
truncate()
działa tak samo w języku programowania C: patrz http://man7.org/linux/man-pages/man2/truncate.2.htmlźródło
Neither truncate nor open(..., 'w') will change the inode number of the file
Dlaczego to jest ważne?file='path/test.xml' with open(file, 'w') as filetowrite: filetowrite.write('new content')
Otwórz plik w trybie 'w', będziesz mógł zamienić jego obecny tekst i zapisać plik z nową zawartością.
źródło
Używając
truncate()
, rozwiązaniem może byćimport 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()
źródło
seek
itruncate
!!! Nie mogłem zrozumieć, dlaczegoseek
sam nie działa.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
Miałem podobny problem i zamiast nadpisywać mój istniejący plik przy użyciu różnych „trybów”, po prostu usunąłem plik przed ponownym użyciem, aby wyglądało to tak, jakbym dołączał do nowego pliku przy każdym uruchomieniu mojego kodu .
źródło
Zobacz artykuł Jak zamienić ciąg w pliku działa w prosty sposób i jest odpowiedzią, która działa z
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()
źródło
Korzystanie z biblioteki 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))
Podobna metoda wykorzystująca inne podejście do kopii zapasowych:
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))
źródło