关于shutil:python:如何快速复制文件

Python: How to Copy Files Fast

本问题已经有最佳答案,请猛点这里访问。

使用shutil.copyfile()复制文件至少需要3倍的时间,而使用Windows文件资源管理器或Mac的finder,则通常右键单击复制>右键单击粘贴。在python中有没有比shutil.copyfile()更快的替代方案?如何加快文件复制过程?(文件目标位于网络驱动器上…如果有什么不同……)。

稍后编辑:

以下是我的结论:

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,''))