打开文件、读取、处理和写回—Python中最短的方法

打开文件、读取、处理和写回—Python中最短的方法,python,coding-style,Python,Coding Style,我想对一个文件做一些基本的过滤。读它,做处理,写回 我不是在寻找“高尔夫”,而是想用最简单、最优雅的方法来实现这一点。我想到了: 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)

我想对一个文件做一些基本的过滤。读它,做处理,写回

我不是在寻找“高尔夫”,而是想用最简单、最优雅的方法来实现这一点。我想到了:

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
语句使事情变得更短,因为我不必显式地打开和关闭文件

还有其他想法吗?

这似乎可行:

with open(filename, "r+") as f:
    new_txt = process(f.read())
    f.truncate(0)
    f.write(new_txt)

我会选择另一种方式:将文件读取和过滤操作实现为生成器,您将编写更多的代码行,但它将更加灵活、可维护和高性能


请参阅David M.Beazley的,这对于编写此类代码的人来说非常重要。

如果您正在寻找与“perl-pi”相当的python版本,这里有一个非常好的版本:

import fileinput for line in fileinput.input(): # process line 导入文件输入 对于fileinput.input()中的行: #生产线 更多信息,请参阅

通过这种方式,您可以在管道中使用python脚本创建新文件:

$ myscript.py infile.txt > outfile.txt $myscript.py infle.txt>outfile.txt
以一种不会在中途崩溃的方式进行:

from twisted.python.filepath import FilePath
p = FilePath(filename)
p.setContent(process(p.getContent()))

实际上,使用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),
我丑陋的(但如问题中所述)解决方案


非常好的链接——谢谢!我有点担心调试管道的难度增加,但其威力是不可否认的。测试驱动开发是你的朋友。但这对我没有什么帮助,因为我想写回同一个文件。对于同一个文件,重定向不会以这种方式工作。非常好,感谢您指出这个选项。您还可以使用fileinput中的filelineno()函数自动获得行号,而不必自己计算。哦,打印后您忘记了逗号-代码添加了额外的换行符:-)感谢您捕捉到了这一点--我已更改了示例。仅当在
f.truncate(0)
之后调用
f.seek(0)
时才在此处起作用,否则,新文件以11个零字节开始(Linux上的Python 2.7.3)。
# 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()))