我想对文件进行一些基本过滤。读它,做处理,写回来。
我不是在寻找“打高尔夫球”,而是想要最简单,最优雅的方法来实现这一目标。我提出了:
from __future__ import with_statement
filename = "..." # or sys.argv...
with open(filename) as f:
new_txt = # ...some translation of f.read()
open(filename, 'w').write(new_txt)
with
语句缩短了时间,因为我不必显式打开和关闭文件。
还有其他想法吗?
答案 0 :(得分:26)
实际上,使用fileinput更简单的方法是使用inplace参数:
import fileinput
for line in fileinput.input (filenameToProcess, inplace=1):
process (line)
如果您使用inplace参数,它会将stdout重定向到您的文件,因此如果您执行打印,它将回写到您的文件。
此示例为您的文件添加行号:
import fileinput
for line in fileinput.input ("b.txt",inplace=1):
print "%d: %s" % (fileinput.lineno(),line),
答案 1 :(得分:4)
我会以不同的方式追求优雅:将文件读取和过滤操作实现为生成器,您将编写更多代码行,但它将更灵活,可维护且性能更佳。
请参阅David M. Beazley的Generator Tricks for Systems Programmers,对于编写此类代码的人来说,这是非常重要的事情。
答案 2 :(得分:3)
这似乎有效:
with open(filename, "r+") as f:
new_txt = process(f.read())
f.truncate(0)
f.write(new_txt)
答案 3 :(得分:2)
如果你正在寻找相当于“perl -pi”的python,这里有一个非常好的:
import fileinput for line in fileinput.input(): # process line
有关详情,请参阅http://www.python.org/doc/2.5.2/lib/module-fileinput.html。
通过这种方式,您可以在管道中使用python脚本来创建新文件:
$ myscript.py infile.txt > outfile.txt
答案 4 :(得分:1)
如果你在中间崩溃,那么就不会eat your data这样做:
from twisted.python.filepath import FilePath
p = FilePath(filename)
p.setContent(process(p.getContent()))
答案 5 :(得分:0)
我的丑陋(但问题中陈述的简短)解决方案generator expressions;
# Some setup first
file('test.txt', 'w').write('\n'.join('%05d' % i for i in range(100)))
# This is the filter function
def f(i):
return i % 3
# This is the main part
file('test2.txt', 'w').write('\n'.join(str(f(int(l))) for l in file('test.txt', 'r').readlines()))
# And a wrapper for sanity
def filter_file(infile, outfile, filter_function)
outfile.write('\n'.join(filter_function(l) for l in infile.readlines()))