【问题标题】:Open a file for input and output in Python在 Python 中打开一个文件进行输入和输出
【发布时间】:2012-07-26 15:12:29
【问题描述】:

我有以下代码,旨在删除文件的特​​定行。当我运行它时,它会打印目录中的两个文件名,然后删除其中的所有信息。我究竟做错了什么?我在 Windows 下使用 Python 3.2。

import os

files = [file for file in os.listdir() if file.split(".")[-1] == "txt"]

for file in files:
    print(file)
    input = open(file,"r")
    output = open(file,"w")

    for line in input:
        print(line)
        # if line is good, write it to output

    input.close()
    output.close()

【问题讨论】:

  • 注意:您应该使用os.path.splitext 来获取文件扩展名。您还应该阅读该文件,然后再写入。
  • 你想写入你打开阅读的同一个文件吗?
  • @jamylak:不,正确的解决方案是迭代glob.iglob("*.txt")
  • @SvenMarnach 好的,但我只是想检查文件扩展名。
  • @poke,这是 for 循环内部的注释。在运行代码之前,我会在那里放一些东西。

标签: python file python-3.x


【解决方案1】:

open(file, 'w') 擦除文件。为防止这种情况发生,请以r+ 模式(读+写/不擦除)打开它,然后一次读取所有内容,过滤行,然后再次将它们写回。类似的东西

with open(file, "r+") as f:
    lines = f.readlines()              # read entire file into memory
    f.seek(0)                          # go back to the beginning of the file
    f.writelines(filter(good, lines))  # dump the filtered lines back
    f.truncate()                       # wipe the remains of the old file

我假设good 是一个告诉是否应该保留一行的函数。

【讨论】:

    【解决方案2】:

    如果您的文件适合内存,最简单的解决方案是打开文件进行读取,将其内容读取到内存,关闭文件,打开文件进行写入并将过滤后的输出写回:

    with open(file_name) as f:
        lines = list(f)
    # filter lines
    with open(file_name, "w") as f:      # This removes the file contents
        f.writelines(lines)
    

    由于您没有混合读写操作,因此这里不需要像"r+" 这样的高级文件模式,只会使事情复杂化。

    如果文件不适合内存,通常的方法是将输出写入一个新的临时文件,并在处理完成后将其移回原始文件名。

    【讨论】:

    • 但是,r+ 有一个很好的特性,即当文件无法打开进行读取时会提前失败。
    • @larsmans:因此,在无论如何都无法完成工作的情况下,它将节省几分之一秒。我认为这不值得麻烦。
    【解决方案3】:

    一种方法是使用fileinput stdlib 模块。那么您就不必担心打开/关闭和文件模式等...

    import fileinput
    from contextlib import closing
    import os
    
    fnames = [fname for fname in os.listdir() if fname.split(".")[-1] == "txt"] # use splitext
    with closing(fileinput.input(fnames, inplace=True)) as fin:
        for line in fin:
            # some condition
            if 'z' not in line: # your condition here
                print line, # suppress new line but adjust for py3 - print(line, eol='') ?
    

    当使用inplace=True - 文件输入重定向stdout 到当前打开的文件。创建具有默认“.bak”扩展名的文件的备份,如果需要,它可能会派上用场。

    jon@minerva:~$ cat testtext.txt
    one
    two
    three
    four
    five
    six
    seven
    eight
    nine
    ten
    

    not line.startswith('t')的条件运行上述内容后:

    jon@minerva:~$ cat testtext.txt
    one
    four
    five
    six
    seven
    eight
    nine
    

    【讨论】:

      【解决方案4】:

      当您打开文件进行写入时,您正在删除所有内容。您不能同时对文件进行打开读取和写入。请改用open(file,"r+"),然后在写入任何内容之前将所有行保存到另一个变量中。

      【讨论】:

        【解决方案5】:

        您不应该同时打开同一个文件进行读写。

        “w”表示创建一个空的写。如果该文件已存在,则其数据将被删除。

        因此您可以使用不同的文件名进行写入。

        【讨论】:

          猜你喜欢
          • 2014-03-20
          • 2013-02-01
          • 2019-07-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-06-07
          相关资源
          最近更新 更多