Открыть файл, прочитать его, обработать и написать обратно - самый короткий метод в 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
делает вещи короче, так как мне не нужно явно открывать и закрывать файл.
Любые другие идеи?
Ответы
Ответ 1
На самом деле проще использовать 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),
Ответ 2
Я пошла бы на элегантность по-другому: реализовав операции чтения и фильтрации файлов в качестве генераторов, вы напишете больше строк кода, но это будет более гибкий, поддерживаемый и исполняемый код.
См. David M. Beazley Генераторные трюки для системных программистов, что очень важно для тех, кто пишет этот код для чтения.
Ответ 3
Это работает:
with open(filename, "r+") as f:
new_txt = process(f.read())
f.truncate(0)
f.write(new_txt)
Ответ 4
Если вы ищете эквивалент python "perl -pi", здесь довольно хороший:
import fileinput
for line in fileinput.input():
# process line
Подробнее см. http://www.python.org/doc/2.5.2/lib/module-fileinput.html.
Сделано так, вы использовали бы свой python script в трубе для создания нового файла:
$ myscript.py infile.txt > outfile.txt
Ответ 5
Чтобы сделать это так, чтобы съесть ваши данные, если вы потерпите крах посередине:
from twisted.python.filepath import FilePath
p = FilePath(filename)
p.setContent(process(p.getContent()))
Ответ 6
Мое уродливое (но короткое, как указано в вопросе) решение с выражения генератора;
# 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()))