尽管你大声否认,你可以在这里使用mmap
。
如果您查看mmap
docs 中的构造函数,它需要参数offset
和length
。在大多数平台上,两者都必须是该值或相似值的倍数PAGESIZE
,但这并不太难。
所以:
try:
PAGESIZE = mmap.PAGESIZE
except NameError:
PAGESIZE = mmap.ALLOCATION_GRANULARITY
def overwrite(fileobj, start, end, newbytes):
startoffset, startremainder = divmod(start, PAGESIZE)
offset = startoffset * PAGESIZE
endoffset, endremainder = divmod(end, PAGESIZE)
length = (endoffset + 1) * PAGESIZE - offset
map = mmap.mmap(fileobj.fileno(), offset=offset, length=length,
access=mmap.ACCESS_WRITE)
map[startremainder:startremainder+end-start] = newbytes
这有一个很好的优势,如果len(newbytes) != end - start
你会从 中得到一个很好的异常mmap
,而不是覆盖比你预期的更多或更少的文件并留下损坏的东西。
但它可能更容易使用seek
,就像 Martijn Pieters 的回答一样。这是与 相同的功能seek
:
def overwrite(fileobj, start, end, newbytes):
if len(newbytes) != end - start:
raise ValueError('overwrite cannot expand or contract a file')
fileobj.seek(start)
fileobj.write(newbytes)
尽管如此,值得知道mmap
可以做什么,这样您就不会在将来的有用案例中忽略它。
(此外,对于某些版本的 Python,在某些平台上,您可能拥有太大而无法seek
放入的文件。例如,linux/proc/*/map
是一个大小为 的稀疏文件1<<64
,但在某些发行版上,Python 找不到fseeko
,因此找不到比 . 更远的地方了1<<63
。因此,了解其他方法(<code>os.lseekmmap
等)可能会帮助您有一天解决问题。)