【问题标题】:Replace and overwrite instead of appending替换和覆盖而不是追加
【发布时间】:2012-07-13 05:31:11
【问题描述】:

我有以下代码:

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”,即我的旧内容后面是新的“替换”内容。我该怎么做才能删除旧的东西,只保留新的?

【问题讨论】:

  • 当您说“用新内容替换文件中的旧内容”时,您需要读入并转换当前内容data = file.read()。您的意思不是“无需先阅读就盲目地覆盖它”。

标签: python replace


【解决方案1】:

使用python3pathlib库:

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

【讨论】:

    【解决方案2】:

    See from How to Replace String in File 以简单的方式工作,并且是与 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()
    

    【讨论】:

      【解决方案3】:

      您需要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))
      

      truncateopen(..., 'w') 都不会更改文件的 inode 编号(我测试了两次,一次使用 Ubuntu 12.04 NFS,一次使用 ext4)。

      顺便说一句,这与 Python 并没有真正的关系。解释器调用相应的低级 API。 truncate() 方法在 C 编程语言中的工作方式相同:参见 http://man7.org/linux/man-pages/man2/truncate.2.html

      【讨论】:

      • Neither truncate nor open(..., 'w') will change the inode number of the file 为什么它很重要?
      • @rok 如果 inode 更改与否在大多数情况下不相关。仅在使用硬链接的极端情况下,但I advice to avoid hard links
      • 使用“f.seek() ...”方法比“with open(...)”方法有缺点吗?
      【解决方案4】:
      file='path/test.xml' 
      with open(file, 'w') as filetowrite:
          filetowrite.write('new content')
      

      以'w'模式打开文件,你将能够用新的内容替换它当前的文本保存文件。

      【讨论】:

      • 这是清除文件并写入新内容的好方法,但问题是关于读取文件、修改内容并用新内容覆盖原始文件。
      • @Boris,先读取文件然后使用此答案中的代码有什么问题?
      • @Rayhunter:效率低下
      • 简单高效,完美完成工作。
      【解决方案5】:
      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
      

      我遇到了类似的问题,我没有使用不同的“模式”覆盖我现有的文件,而是在再次使用它之前删除了该文件,这样就好像我在每次运行时都附加到一个新文件一样我的代码。

      【讨论】:

        【解决方案6】:

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

        【讨论】:

        • seek truncate!!!我无法弄清楚为什么单独使用 seek 不起作用。
        猜你喜欢
        • 1970-01-01
        • 2011-11-23
        • 2016-06-19
        • 1970-01-01
        • 2016-10-25
        • 2010-12-13
        • 1970-01-01
        • 2018-02-25
        相关资源
        最近更新 更多