2008-10-22 51 views
13

我想對文件進行一些基本的過濾。閱讀它,做處理,寫回。打開文件,讀取它,處理並寫回 - 在Python中最短的方法

我不是在尋找「打高爾夫球」,而是想要最簡單最優雅的方法來實現這一點。我想出了:

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聲明讓事情更短,因爲我沒有明確地打開和關閉文件。

還有其他想法嗎?

回答

25

實際使用的FileInput一個簡單的方法是使用就地參數:

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), 
3

這似乎工作:

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

只有在`f.truncate(0)`後面調用`f.seek(0)`時才適用,否則新文件以11個零字節(Linux上的Python 2.7.3)開頭。 – scai 2012-09-07 11:14:08

4

我會去的優雅不同的方式:執行你的文件讀取和過濾操作爲發電機,你會寫更多的代碼,但它會更靈活,可維護和高性能的代碼。

查看David M. Beazley的Generator Tricks for Systems Programmers,這對於任何編寫這類代碼的人來說都是非常重要的。

+0

優秀的鏈接 - 謝謝!我有點擔心調試管道的難度增加,但這種力量是不可否認的。 – 2008-10-23 04:09:35

+1

測試驅動開發是你的朋友。 – 2008-10-23 09:00:16

2

如果您正在尋找蟒蛇相當於「的perl -pi」,這裏是一個相當不錯的:

 
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 
+0

雖然這並沒有真正幫助我,因爲我想回寫同一個文件。對於同一個文件,重定向不會以這種方式工作 – 2008-10-23 16:16:53

1

要做到這一點的不會eat your data,如果你在中間崩潰其中一種方式:

from twisted.python.filepath import FilePath 
p = FilePath(filename) 
p.setContent(process(p.getContent())) 
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())) 
相關問題