अपडाउन करने के बजाय बदलें और ओवरराइट करें


102

मेरे पास निम्नलिखित कोड हैं:

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

जहाँ मैं उस पुरानी सामग्री को बदलना चाहता हूँ जो नई सामग्री के साथ फाइल में है। हालाँकि, जब मैं अपने कोड को निष्पादित करता हूं, तो फ़ाइल "test.xml" को जोड़ दिया जाता है, अर्थात मेरे पास नई "प्रतिस्थापित" सामग्री द्वारा पुरानी सामग्री follwed है। पुराने सामान को हटाने और केवल नया रखने के लिए मैं क्या कर सकता हूं?



जब आप कहते हैं कि "नई सामग्री वाली फ़ाइल में पुरानी सामग्री को प्रतिस्थापित करें" , तो आपको वर्तमान सामग्रियों को पढ़ने और बदलने की आवश्यकता है data = file.read()। आपका मतलब यह नहीं है "पहले इसे पढ़ने की आवश्यकता के बिना नेत्रहीन इसे अधिलेखित करें"।
18'18

जवाबों:


112

आपको seekलिखने से पहले फ़ाइल की शुरुआत करने की आवश्यकता है और फिर file.truncate()यदि आप इनप्लेस को प्रतिस्थापित करना चाहते हैं तो उपयोग करें :

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

दूसरा रास्ता तो साथ फिर से खोल फ़ाइल को पढ़ने के लिए है 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))

न तो truncateहै और न ही open(..., 'w')बदल जाएगा inode फ़ाइल की संख्या (मैं दो बार परीक्षण किया है, Ubuntu 12.04 एनएफएस के साथ एक बार और ext4 के साथ एक बार)।

वैसे, यह वास्तव में पायथन से संबंधित नहीं है। दुभाषिया संबंधित निम्न स्तर एपीआई को कॉल करता है। truncate()C प्रोग्रामिंग भाषा में विधि समान है: http://man7.org/linux/man-pages/man2/trunbate.2.html देखें


Neither truncate nor open(..., 'w') will change the inode number of the fileयह महत्वपूर्ण क्यों है?
ROK

@rok अगर इनोड बदलता है या ज्यादातर मामलों में प्रासंगिक नहीं है। केवल किनारे के मामलों में जहां आप हार्ड-लिंक का उपयोग करते हैं, लेकिन मैं हार्ड लिंक से बचने की सलाह देता हूं
गुफ्तगू

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

फ़ाइल को 'w' मोड में खोलें, आप फ़ाइल को नई सामग्री से बचाने के लिए इसके वर्तमान पाठ को बदल पाएंगे।


6
किसी फ़ाइल को साफ़ करने और उसके लिए कुछ नया लिखने का यह एक अच्छा तरीका है, लेकिन सवाल फ़ाइल को पढ़ने, सामग्री को संशोधित करने और नई सामग्री के साथ मूल को ओवरराइट करने के बारे में था।
बोरिस

1
@ बोरिस, फ़ाइल को पहले पढ़ने और फिर इस उत्तर में कोड का उपयोग करने में क्या समस्या है?
रेहन्टर

@ रेहनटर: यह अक्षम है
सर्व-इन-

यह सरल और कुशल है, सही तरीके से काम करता है।
चिक्कू जैकब

16

का उपयोग करते हुए truncate(), समाधान हो सकता है

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 और truncate !!! मैं यह पता नहीं लगा सका कि seekअकेले काम क्यों नहीं कर रहा था।
coner.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

मुझे इसी तरह की समस्या थी, और अलग-अलग 'मोड्स' का उपयोग करके अपनी मौजूदा फ़ाइल को ओवरराइट करने के बजाय, मैंने इसे फिर से उपयोग करने से पहले फ़ाइल को हटा दिया, ताकि यह ऐसा हो जैसे कि मैं अपने कोड के प्रत्येक रन पर एक नई फ़ाइल को जोड़ रहा हूं ।



0

Python3 pathlib लाइब्रेरी का उपयोग करना :

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

बैकअप के लिए अलग-अलग दृष्टिकोण का उपयोग करने वाली समान विधि:

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))
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.