输出相同时不轻易覆盖文件的简便方法

时间:2012-01-03 21:29:55

标签: python cmake

我在Python中有一个C ++代码生成器,可以生成许多源文件。大多数情况下,只有一个文件发生更改,但由于生成器会重新生成所有文件,因此它们都会重建。有没有办法让Python不覆盖文件,或者让cmak使用校验和来查看需要重建的内容而不仅仅是使用文件日期?

我认为这样的事情在Python中很容易:如果我可以替换

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

用这个:

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

实现这一目标的好方法是什么?

4 个答案:

答案 0 :(得分:4)

结合Neil GPetr Viktoringeccojoel3000的代码和想法:

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)

一些小的补充(希望改进):

  • shutil.copyfile仅将tempname的内容复制到。{1}}中 filename,同时保留文件权限和文件等元数据 所有权。
  • filecmp.cmp检查文件的大小 如果尺寸不匹配,则返回False。那可能很不错 加速,如果文件很大,一个附加的东西 结束。它还一次读取并比较bufsize = 8*1024个字节, 而不是一次一行。 bufsize通常会大于a 行,这将导致更少的读取。

答案 1 :(得分:3)

我建议你像这样编写我们自己的文件对象:

  • __enter__:创建临时文件
  • __exit__:比较临时文件的内容与旧文件(如果存在)如果它们不相同,则用临时文件替换旧文件

本文非常有助于理解with声明:Understanding Python's "with" statement

答案 2 :(得分:3)

使用filecmp - http://docs.python.org/library/filecmp.html

将新文件写入tmp目录,与工作目录进行比较 ,并转移更改的文件。然后删除tmp。

答案 3 :(得分:0)

最简单的方法是在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