【问题标题】:Can I read and overwrite using 'open' only once?我可以只使用“打开”一次读取和覆盖吗?
【发布时间】:2017-01-16 09:12:06
【问题描述】:

有 1000 多个 html 文件。

我想做:

  • 读取文件。
  • 修剪特定行。
  • 覆盖文件(不追加)。

以下代码有效。但我认为两次使用“开放”是浪费。我可以写得更简单吗?

for file_path in glob.glob(os.path.join(dir, '*.html')):
    with open(file_path, "r", encoding="utf-8") as reader:
        html_ = reader.read()
        replaced = html_.replace("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>", "")
        with open(file_path, "w", encoding="utf-8") as writer:
            writer.write(replaced)

我试过了:

  • 'r+':这是加法。
  • 'w+': read() 方法返回 ''

【问题讨论】:

    标签: python file python-3.x file-io


    【解决方案1】:

    是的,以'r+'模式打开文件,阅读后'rewind'(seek返回开始):

    with open(file_path, "r+", encoding="utf-8") as f:
        html_ = f.read()
        f.seek(0)
        replaced = html_.replace("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>", "")
        f.write(replaced)
        f.truncate()
    

    我还添加了一个file.truncate() 调用,因为您要从文件中删除数据。如果没有该调用,您将不会替换文件中的 all 数据,最后仍然会有 len(removed_data) 字节。

    您的尝试失败了,因为您在使用'r+' 时没有回到起点(因此写入开始于读取停止的点,即文件末尾),并且'w+' 首先截断文件 (因此将长度设置为 0,删除内容)。

    替代方法是使用fileinput module;它使您可以用一种更简单的方法就地替换文件内容:

    import fileinput
    
    with fileinput.input(file_path, inplace=True, openhook=fileinput.hook_encoded("utf-8")) as f:
        html_ = f.read()
        replaced = html_.replace("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>", "")
        print(replaced, end='')
    

    使用inplace=True,旧文件将移至&lt;filename&gt;.bak 为您备份,打印会将输出定向到在原始位置打开的新文件。

    【讨论】:

    • 关于效率,使用FileInput并原地更改不是更好吗?
    • @JimFasarakis-Hilliard:FileInput 将创建一个单独的文件并将其移至旧位置。这不一定更有效。
    • 谢谢。我懂了。我明白当我调用 read() 时,指针会前进。当我调用 write() 时,作家从那一刻开始写作。非常感谢您可以理解的解释。我也调用 truncate()。
    • @JimFasarakis-Hilliard:fileinput 模块的最大问题是打开过程的混淆程度,这使得指定编码和错误处理程序比它需要的要困难得多。尝试以 locale.getpreferredencoding() 以外的编码打开文件对象(在 Windows 上几乎总是错误,在其他人上通常是错误的)。我wrote a replacement implementation 一次。
    • @JimFasarakis-Hilliard:该模块确实有一个辅助函数fileinput.hook_encoded(),但只有从 Python 3.6 开始,您才能指定错误处理程序,而无需编写自己的钩子。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多