Python: How to Copy Files Fast
本问题已经有最佳答案,请猛点这里访问。
使用
以下是我的结论:
1 2 3 4 5 6 7 8 9 10 11 12 | def copyWithSubprocess(cmd): proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) win=mac=False if sys.platform.startswith("darwin"):mac=True elif sys.platform.startswith("win"):win=True cmd=None if mac: cmd=['cp', source, dest] elif win: cmd=['xcopy', source, dest, '/K/O/X'] if cmd: copyWithSubprocess(cmd) |
最快的版本没有过度优化我用以下代码得到的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | class CTError(Exception): def __init__(self, errors): self.errors = errors try: O_BINARY = os.O_BINARY except: O_BINARY = 0 READ_FLAGS = os.O_RDONLY | O_BINARY WRITE_FLAGS = os.O_WRONLY | os.O_CREAT | os.O_TRUNC | O_BINARY BUFFER_SIZE = 128*1024 def copyfile(src, dst): try: fin = os.open(src, READ_FLAGS) stat = os.fstat(fin) fout = os.open(dst, WRITE_FLAGS, stat.st_mode) for x in iter(lambda: os.read(fin, BUFFER_SIZE),""): os.write(fout, x) finally: try: os.close(fin) except: pass try: os.close(fout) except: pass def copytree(src, dst, symlinks=False, ignore=[]): names = os.listdir(src) if not os.path.exists(dst): os.makedirs(dst) errors = [] for name in names: if name in ignore: continue srcname = os.path.join(src, name) dstname = os.path.join(dst, name) try: if symlinks and os.path.islink(srcname): linkto = os.readlink(srcname) os.symlink(linkto, dstname) elif os.path.isdir(srcname): copytree(srcname, dstname, symlinks, ignore) else: copyfile(srcname, dstname) # XXX What about devices, sockets etc.? except (IOError, os.error), why: errors.append((srcname, dstname, str(why))) except CTError, err: errors.extend(err.errors) if errors: raise CTError(errors) |
这段代码的运行速度比本机Linux"cp-rf"慢一点。
与shutil相比,本地存储到tmfps的增益约为2x-3x,而对于nfs到本地存储的增益约为6x。
在分析之后,我注意到shutil.copy做了很多fstat系统,这些系统相当重。如果想进一步优化,我建议对SRC执行单个fstat并重用这些值。老实说,我没有做得更进一步,因为我得到了与本机Linux拷贝工具几乎相同的数字,并且优化了几百毫秒并不是我的目标。
对于Windows,您只需使用正在进行复制的操作系统即可:
1 2 | from subprocess import call call(["xcopy","c:\\file.txt","n:\\folder\","/K/O/X"]) |
/k-复制属性。通常,xcopy会重置只读属性< BR>/o-复制文件所有权和ACL信息。< BR>/x-复制文件审核设置(暗示/o)。
1 2 3 4 5 6 7 8 9 10 11 | import sys import subprocess def copyWithSubprocess(cmd): proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) cmd=None if sys.platform.startswith("darwin"): cmd=['cp', source, dest] elif sys.platform.startswith("win"): cmd=['xcopy', source, dest, '/K/O/X'] if cmd: copyWithSubprocess(cmd) |
这只是个猜测,但是…你的时机不对…也就是说,当您复制文件时,它会打开文件并将其全部读取到内存中,这样当您粘贴文件时,您只会创建一个文件并转储内存内容。
在Python中
1 | copied_file = open("some_file").read() |
是ctrl+c副本的等效项
然后
1 2 | with open("new_file","wb") as f: f.write(copied_file) |
是ctrl+vbkbd粘贴的等量(因此,等量时间…)
如果您希望它能够更大范围地扩展到更大的数据(但其速度不如ctrl+v/ctrl+c
1 2 | with open(infile,"rb") as fin,open(outfile,"wb") as fout: fout.writelines(iter(fin.readline,'')) |