Question

Il faut au moins 3 fois plus de temps pour copier des fichiers avec shutil.copyfile() par rapport à un clic droit-copier> clic droit-coller à l'aide de l'Explorateur de fichiers Windows ou du Finder de Mac.Existe-t-il une alternative plus rapide à shutil.copyfile() en Python ?Que pourrait-on faire pour accélérer le processus de copie de fichiers ?(La destination des fichiers est sur le lecteur réseau...si ça fait une différence...).

ÉDITÉ PLUS TARD :

Voici ce avec quoi j'ai fini:

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)
Était-ce utile?

La solution

La version la plus rapide sans suroptimisation du code que j'ai avec le code suivant :

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)

Ce code s'exécute un peu plus lentement que "cp -rf" natif de Linux.

En comparaison avec Shutil, le gain pour le stockage local par rapport à tmfps est d'environ 2x-3x et d'environ 6x pour NFS vers le stockage local.

Après le profilage, j'ai remarqué queshutil.copy fait beaucoup de syscals fstat qui sont assez lourds.Si l'on souhaite optimiser davantage, je suggère de faire un seul fstat pour src et de réutiliser les valeurs.Honnêtement, je ne suis pas allé plus loin car j'ai obtenu presque les mêmes chiffres que l'outil de copie natif de Linux et l'optimisation sur plusieurs centaines de millisecondes n'était pas mon objectif.

Autres conseils

Vous pouvez simplement utiliser le système d'exploitation sur lequel vous effectuez la copie, pour Windows :

from subprocess import call
call(["xcopy", "c:\\file.txt", "n:\\folder\\", "/K/O/X"])

/K - Copie les attributs.Généralement, Xcopy réinitialise les attributs en lecture seule
/O - Copie la propriété du fichier et les informations ACL.
/X - Copie les paramètres d'audit des fichiers (implique /O).

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)

ce n'est qu'une supposition mais... tu as mal chronométré ...c'est-à-dire que lorsque vous copiez le fichier, il ouvre le fichier et le lit en mémoire de sorte que lorsque vous collez, vous créez uniquement un fichier et videz le contenu de votre mémoire.

en python

copied_file = open("some_file").read()

est l'équivalent du Ctrl + c copie

alors

with open("new_file","wb") as f:
     f.write(copied_file)

est l'équivalent du Ctrl + v coller (donc le temps que pour l'équivalence....)

si vous voulez qu'il soit plus évolutif pour des données plus volumineuses (mais cela ne sera pas aussi rapide que ctrl+v /ctrl+c

with open(infile,"rb") as fin,open(outfile,"wb") as fout:
     fout.writelines(iter(fin.readline,''))
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top