python - 将(生成的) header 添加到许多文件的最有效方法?

标签 python file-io python-2.6

我正在编写一个脚本,用于检查/创建/更新项目中源文件顶部的版权声明。

这通常是 I/O 限制,因为每次使用脚本时, header (丢失或以其他方式)往往会变大(例如,在现有通知中添加更多年份),因此必须重新定位文件的其余部分到以后的偏移量。这意味着读取整个文件,然后将其写回(+我想要的小标题更改)。

我想到可能有一种更有效的方法来做到这一点。这个用例并不少见,不是吗?


我天真地想象,可以像寻找文件末尾之后一样寻找负偏移量(这通常会导致稀疏文件)。

import os
fh = file("code.py", "rb+")
original_size = os.fstat( fh.fileno() ).st_size
data = fh.read()

# `prefix` should be prepended to the file
# `updated_data` is anchored to offset 0, and likely only a 
#    few 10s of bytes long (unlike the original file)
# `suffix should` be postpended to the file
prefix, updated_data, suffix = get_changes(data)

fh.seek(0)
fh.write(updated_data)

# WISHFUL THINKING. Not possible to seek to a negative offset.
fh.seek( -1 * len(prefix) )
fh.write(prefix)

fh.seek( max(original_size, len(updated_data)) )
fh.write(suffix)

fh.close()

环境问题:

  • Python v2.6
  • GNU/Linux(Red Hat Enterprise 5 + Ubuntu 10.04,如果需要的话)

最佳答案

如果将 whence 参数传递给 file.seek,则可以寻求负索引。 ,否则假定为绝对值(因此不允许使用负位置)。

import os
f = open('insert.txt', 'r+')
f.seek(3)
f.seek(-1, os.SEEK_CUR) # will go back one position
f.seek(-1, os.SEEK_END) # one position before the end of the file

不过,这并不会真正帮助你 - 在中间写入字节会覆盖现有字节,而不是向前打乱所有内容。

您可以通过在文件开头保留固定数量的 header 字节来实现您想要的目的 - 这就是二进制文件格式如何避免在更改时必须写出整个文件。不过,我不推荐将其用于源文件。这将很容易出错 - 如果你弄错了(或者你想写的 header 太长),那么你的代码的开头可能会被 header 维护脚本覆盖。

不过,混合方法可能会奏效。

  • 第一次处理文件时,以缓慢的方式写入 header (再次写出整个文件),为将来的增长保留一些额外的空间,并在 header 的末尾放置一个标记。哨兵应该是人类可读的,并且很容易不会被无意中破坏。
  • 然后,下次需要写入标题时,读入标题(直到您知道需要的长度)。如果哨兵位于正确的位置,您可以使用快速覆盖技术。
  • 如果没有,您需要再次以慢速方式写入 header 。

一些代码(不处理标题大小更改):

import sys
import os

RESERVED = 40
SENTINEL = '\n### HEADER ENDS ###\n'

def pad(heading):
    free_space = RESERVED - len(heading)
    padding = ('#' * free_space) if free_space > 0 else ''
    return heading + padding

def _write_header_slow(fname, text):
    # Do this in chunks instead if you have large files.
    dest = fname + '.temp'
    with open(fname) as infile:
        content = infile.read()
    with open(dest, 'w') as outfile:
        outfile.write(text)
        outfile.write(SENTINEL)
        outfile.write(content)
    os.rename(dest, fname)

def write_header(fname, text):
    if not text.endswith('\n'):
        text += '\n'
    assert len(text) < RESERVED, 'too much for the header!'
    padded = pad(text)
    with open(fname, 'rb+') as f:
        current_header = f.read(RESERVED + len(SENTINEL))
        if current_header.endswith(SENTINEL):
            f.seek(0)
            print 'fast path!'
            f.write(padded)
        else:
            print 'slow path ):'
            _write_header_slow(fname, text)

if __name__ == '__main__':
    write_header(sys.argv[1], sys.argv[2])

关于python - 将(生成的) header 添加到许多文件的最有效方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8389393/

相关文章:

python - 检查 numpy 数组是否具有正常形状

file-io - Camel 无法选取 0 字节文件

ssh - Fabric 似乎启动了 apache2,但没有启动

python - 是否可以访问在标准输入中传递给 python 的 python 脚本的源代码?

python - 如何从 pandas Dataframe groupby 对象获取一系列 json/字典

python - 为什么使用相同的数据集进行训练和测试会产生不同的准确性?

file-io - 卸载自定义操作 (InstallShield) 期间删除文件时出错

c++ - 为什么它只在第二次正确读取文件

Python : Ensure string is exactly in A. B.C 格式 ..(两个点分隔 3 个字符串)

python - 没有名为 _cffi_backend 的模块