Простой способ не перезаписывать файл при одинаковом выводе - PullRequest
3 голосов
/ 04 января 2012

У меня есть генератор кода C ++ в Python, который генерирует много исходных файлов. В большинстве случаев изменяется только один файл, но поскольку генераторы регенерируют все файлы, они все перестраиваются. Есть ли способ заставить Python не перезаписывать файлы, или же заставить cmak использовать контрольную сумму, чтобы увидеть, что нужно восстановить, а не просто использовать дату файла?

Я думал, что что-то вроде этого будет легко в Python: если бы я мог заменить

with open('blah', 'w') as f:

с этим:

with open_but_only_overwrite_if_total_output_is_different('blah', 'w') as f:

Какой хороший способ сделать это?

Ответы [ 4 ]

4 голосов
/ 05 января 2012

Объединение кода и идей Нейла Г , Петра Викторина , gecco и joel3000 :

import contextlib
@contextlib.contextmanager
def write_on_change(filename):
    with tempfile.NamedTemporaryFile(delete=False) as f:
        yield f
        tempname = f.name
    try:
        overwrite = not filecmp.cmp(tempname,filename)
    except (OSError,IOError):
        overwrite = True
    if overwrite:
        shutil.copyfile(tempname,filename)
    os.unlink(tempname)

Некоторые небольшие дополнения (надеюсь, улучшения):

3 голосов
/ 04 января 2012

Использовать filecmp - http://docs.python.org/library/filecmp.html.

Запишите новые файлы в каталог tmp, сравните их с вашим рабочим каталогом и перенесите поверх измененных файлов.Затем удалите tmp.

3 голосов
/ 04 января 2012

Я бы предложил вам написать наш собственный подобный файлу объект, подобный этому:

  • __enter__: Создать временный файл
  • __exit__: Сравнить содержимое временного файласо старым файлом (если существует) Если они не совпадают, то замените старый файл временным файлом

Эта статья очень полезна для понимания оператора with: Понимание выражения Python "with"

0 голосов
/ 04 января 2012

Самый простой способ - это сделать в Python именно то, что делает cmake: заставить генератор проверить, является ли вход новее, чем вывод, и генерировать только, если он есть.

Вот фрагмент, который я использовал для чего-то похожего:

if (os.path.exists(output) and
    os.path.getmtime(source) <= os.path.getmtime(output)):
    print "Generated output %s is up-to-date." % output
    return
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...