使用Python中的直接方法复制文件通常是这样的:
def copyfileobj(fsrc, fdst, length=16*1024):
"""copy data from file-like object fsrc to file-like object fdst"""
while 1:
buf = fsrc.read(length)
if not buf:
break
fdst.write(buf)
(顺便说一句,此代码段来自shutil.py.)
不幸的是,这在我的特殊用例中有缺点(涉及线程和非常大的缓冲区)[稍后添加的斜体部分] 。首先,这意味着每次调用read()时都会分配一个新的内存块,并且当在下一次迭代中覆盖buf时,将释放该内存,仅为了相同的目的再次分配新的内存。这会降低整个过程的速度,并给主机带来不必要的负担。
为了避免这种情况,我正在使用file.readinto()方法,遗憾的是,该方法被记录为已弃用且“不使用”:
def copyfileobj(fsrc, fdst, length=16*1024):
"""copy data from file-like object fsrc to file-like object fdst"""
buffer = array.array('c')
buffer.fromstring('-' * length)
while True:
count = fsrc.readinto(buffer)
if count == 0:
break
if count != len(buffer):
fdst.write(buffer.toString()[:count])
else:
buf.tofile(fdst)
我的解决方案有效,但也有两个缺点:首先,不使用readinto()。它可能会消失(文档说)。第二,使用readinto()我无法确定我想要读入缓冲区的多少字节以及buffer.tofile()我无法确定我想写多少字节,因此最后一个块的繁琐特殊情况(这也是不必要的昂贵的)。
我查看了array.array.fromfile(),但它不能用于读取“all there is”(读取,然后抛出EOFError并且不会分发已处理的项目数)。对于结束特殊情况问题,它也没有解决方案。
有没有正确的方法来做我想做的事情?也许我只是忽略了一个简单的缓冲类或类似的东西来做我想要的。
答案 0 :(得分:3)
此代码段来自shutil.py
哪个是标准库模块。为什么不直接使用呢?
首先,这意味着每次调用read()时都会分配一个新的内存块,并且在下一次迭代中覆盖buf时,将释放该内存,仅为了相同的目的再次分配新的内存。这会降低整个过程的速度,并给主机带来不必要的负担。
与实际从磁盘中获取数据页所需的工作相比,这是微不足道的。
答案 1 :(得分:2)
正常的Python代码不需要这样的调整 - 但是如果你真的需要所有的性能调整来从Python代码中读取文件(就像在,你正在重写一些服务器系列你写的并且已经工作了性能或内存使用情况)我宁愿直接使用ctypes调用操作系统 - 因此副本的执行级别也低于我想要的级别。
甚至可能简单地将“cp”可执行文件作为外部进程调用在您的情况下不是一个障碍(并且它将充分利用所有操作系统和文件系统级别优化)。