2008-10-22 4 views
13

Chcę wykonać podstawowe filtrowanie pliku. Przeczytaj to, przetwarzaj, zapisz.Otwórz plik, przeczytaj go, przetwórz i odpisz - najkrótsza metoda w Pythonie

Nie szukam "golfa", ale chcę najprostszej i najbardziej eleganckiej metody, aby to osiągnąć. Wpadłem:

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) 

Oświadczenie with sprawia, że ​​rzeczy krótsze, ponieważ nie trzeba jawnie otwarte i zamknij plik.

Jakieś inne pomysły?

Odpowiedz

25

Właściwie łatwiejszy sposób korzystania fileinput jest użycie inplace parametr:

import fileinput 
for line in fileinput.input (filenameToProcess, inplace=1): 
    process (line) 

Jeśli użyjesz parametru inplace, przekieruje on stdout do twojego pliku, więc jeśli wykonasz wydruk, prześle go z powrotem do twojego pliku.

Ten przykład dodaje numery linii do pliku:

import fileinput 

for line in fileinput.input ("b.txt",inplace=1): 
    print "%d: %s" % (fileinput.lineno(),line), 
+0

Bardzo ładne, dzięki za wskazanie tej opcji. Możesz także użyć funkcji filelineno() z fileinput, aby automatycznie uzyskać numer wiersza, nie licząc go samodzielnie. –

+1

Aha, i zapomniałeś przecinka po wydruku - kod dodaje dodatkowe znaki nowej linii :-) –

+0

Dzięki za złapanie tego - zmieniłem przykład. – Hortitude

3

To wydaje się działać:

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

Działa tu tylko wtedy, gdy wywołanie 'f.seek (0)' 'po f.truncate (0)', w przeciwnym razie nowy plik zaczyna się od zera 11 bajtów (Python 2.7.3 na Linux). – scai

4

pójdę do elegancji inny sposób: wdrożyć plik czytaniu i filtrowania operacji jak generatory, będziemy pisać więcej linii kodu, ale będzie więcej elastyczny, konserwowalny i wydajny kod.

Zobacz David M. Beazley's Generator Tricks for Systems Programmers, co jest naprawdę ważne dla każdego, kto pisze ten rodzaj kodu do przeczytania.

+0

Doskonały link - dziękuję! Trochę niepokoję się zwiększoną trudnością w debugowaniu rurociągów, ale moc jest niezaprzeczalna. –

+1

Rozwój oparty na testach jest twoim przyjacielem. –

2

Jeśli szukasz równowartość Pythona z „perl -pi”, tutaj jest dość dobra:

 
import fileinput 
for line in fileinput.input(): 
    # process line 

Zobacz http://www.python.org/doc/2.5.2/lib/module-fileinput.html więcej.

Sporządzono w ten sposób, należy użyć skryptu Pythona w rurze, aby utworzyć nowy plik:

 
$ myscript.py infile.txt > outfile.txt 
+0

To naprawdę nie pomaga mi, ponieważ chcę napisać z powrotem do tego samego pliku. Przekierowanie nie zadziała w ten sposób dla tego samego pliku. –

1

to zrobić w sposób, który nie będzie eat your data jeśli Zawieszenie w środku:

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

My brzydkie (ale krótki, jak zaznaczono w pytaniu) roztworu z 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())) 
Powiązane problemy