Eklemek yerine değiştirin ve üzerine yazın


96

Takip koduna sahibim:

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()

dosyadaki eski içeriği yeni içerikle değiştirmek istiyorum. Bununla birlikte, kodumu çalıştırdığımda, "test.xml" dosyası eklenir, yani eski içeriğe yeni "değiştirilen" içerik ekleniyor. Eskileri silmek ve sadece yenilerini saklamak için ne yapabilirim?



Dediğinizde "yeni içerikle dosyada var eski içerik yerine" , geçerli içeriğini okumak ve dönüştürmeye gerek data = file.read(). "Önce okumaya gerek kalmadan körü körüne üzerine yazın" demek istemiyorsunuz.
smci

Yanıtlar:


105

İhtiyacınız seekkullanmak sonra yazmaya ve daha önce dosyanın başlangıcına file.truncate()Değiştirmeye INPLACE yapmak istiyorsanız:

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()

Diğer bir yol ise dosyayı okumak ve ardından tekrar açmaktır 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))

Ne truncatede open(..., 'w')değişecek inode dosyasının numarası (ben ext4 ile Ubuntu 12.04 NFS ile bir kez ve bir kez iki kez test edildi).

Bu arada, bu gerçekten Python ile ilgili değil. Yorumlayıcı, ilgili düşük seviyeli API'yi çağırır. Yöntem truncate(), C programlama dilinde aynı şekilde çalışır: Bkz. Http://man7.org/linux/man-pages/man2/truncate.2.html


Neither truncate nor open(..., 'w') will change the inode number of the fileneden önemlidir?
rok

İnode değişirse veya çoğu durumda alakalı değilse @rok. Yalnızca sabit bağlantıları kullandığınız uç durumlarda, ancak sabit bağlantılardan kaçınmanızı öneririm .
guettli

67
file='path/test.xml' 
with open(file, 'w') as filetowrite:
    filetowrite.write('new content')

Dosyayı 'w' modunda açın, mevcut metnini değiştirerek dosyayı yeni içerikle kaydedebilirsiniz.


5
Bu, bir dosyayı temizlemenin ve ona yeni bir şey yazmanın iyi bir yoludur, ancak soru, dosyayı okumak, içeriğini değiştirmek ve orijinalin üzerine yeni içeriği yazmakla ilgiliydi.
Boris

15

Kullanarak truncate()çözüm olabilir

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()

1
seek ve truncate !!! Neden seekyalnız başına çalışmadığını anlayamadım.
conner.xyz

2
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

Benzer bir sorun yaşadım ve farklı 'modları' kullanarak mevcut dosyamın üzerine yazmak yerine, dosyayı tekrar kullanmadan önce sildim, böylece kodumun her çalıştırmasında yeni bir dosyaya ekliyormuşum gibi .


1

Dosyadaki Dize Nasıl Değiştirilir konusuna bakın, basit bir şekilde çalışır ve birlikte çalışan bir cevaptır.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()

0

Python3 pathlib kitaplığını kullanma :

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))

Yedeklemelere farklı yaklaşımlar kullanan benzer yöntem:

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))
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.