Domanda

Ci vogliono almeno 3 volte di più per copiare i file con shutil.copyfile() rispetto a un normale tasto destro del mouse-copia > tasto destro del mouse-incolla utilizzando Esplora file di Windows o Finder di Mac.C'è un'alternativa più veloce a shutil.copyfile() in Python?Cosa si potrebbe fare per accelerare un processo di copia dei file?(La destinazione dei file si trova sull'unità di rete...se fa qualche differenza...).

MODIFICATO IN SEGUITO:

Ecco cosa ho finito con:

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)
È stato utile?

Soluzione

La versione più veloce senza sovrastimare il codice che ho con il seguente codice:

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)

Questo codice funziona un po ' più lentamente di Linux nativo "cp-rf".

Confrontando a shutil il guadagno per lo storage locale a tmfps è di circa 2x - 3x e circa di 6x per NFS allo storage locale.

Dopo aver profilato ho notato che shutil.copia fa un sacco di syscal fstat che sono piuttosto pesanti.Se si desidera ottimizzare ulteriormente, suggerirei di fare un singolo fstat per src e riutilizzare i valori.Onestamente non sono andato oltre poiché ho ottenuto quasi le stesse cifre dello strumento di copia Linux nativo e l'ottimizzazione per diversi hundrends di millisecondi non era il mio obiettivo.

Altri suggerimenti

Potresti semplicemente usare il sistema operativo su cui stai facendo la copia, per Windows:

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

/ K-Copia gli attributi.In genere, Xcopy reimposta gli attributi di sola lettura
/ O-Copia la proprietà dei file e le informazioni ACL.
/ X-Copia le impostazioni di controllo dei file (implica / 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)

questa è solo un'ipotesi, ma ... il tuo tempismo è sbagliato ...cioè quando si copia il file si apre il file e legge tutto in memoria in modo che quando si incolla si crei solo un file e si scarichi il contenuto della memoria

in python

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

è l'equivoco del Ctrl + c copia

poi

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

è l'equivoco del Ctrl + v incolla (così il tempo che per equivelency ....)

se vuoi che sia più scalabile per dati più grandi (ma non sarà veloce come ctrl + v / ctrl + c

with open(infile,"rb") as fin,open(outfile,"wb") as fout:
     fout.writelines(iter(fin.readline,''))
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top