我有以下代码,用于删除文件的特定行。当我运行它时,它会打印出目录中的两个文件名,然后删除其中的所有信息。我究竟做错了什么?我在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()
答案 0 :(得分:7)
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
是一个函数,告诉我们是否应保留一行。
答案 1 :(得分:3)
如果您的文件适合内存,最简单的解决方案是打开文件进行读取,将其内容读取到内存,关闭文件,打开文件进行写入并将过滤后的输出写回:
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+"
这样的高级文件模式,只能进行复合。
如果文件不适合内存,通常的方法是将输出写入新的临时文件,并在处理完成后将其移回原始文件名。
答案 2 :(得分:1)
一种方法是使用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
时 - fileinput会将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
答案 3 :(得分:0)
当您打开要写入的文件时,您将删除所有内容。您不能同时打开和写入文件。改为使用open(file,"r+")
,然后在写入任何内容之前将所有行保存到另一个变量。
答案 4 :(得分:0)
您不应该同时打开同一个文件进行阅读和写作。
“w”表示为写作创建一个空。如果该文件已存在,则其数据将被删除。
因此,您可以使用其他文件名进行书写。