web-dev-qa-db-ja.com

Python:ファイルを高速にコピーする方法

shutil.copyfile()を使用してファイルをコピーするには、WindowsファイルエクスプローラーまたはMacのFinderを使用した通常の右クリックコピー>右クリックペーストよりも少なくとも3倍時間がかかります。 Pythonのshutil.copyfile()に代わる高速な方法はありますか?ファイルのコピープロセスを高速化するにはどうすればよいですか? (ファイルの宛先はネットワークドライブ上にあります...何か違いがある場合...)。

編集後:

これが私が終わったものです:

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)
17
alphanumeric

次のコードで取得したコードを最適化しなかった最速バージョン:

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"よりも少し遅い速度で実行されます。

ローカルストレージの利益をtmfpsに近づけると比較すると、NFSからローカルストレージの場合は約2倍から3倍、約6倍になります。

プロファイリング後、shutil.copyがかなり重いfstat syscalをたくさん実行していることに気付きました。さらに最適化したい場合は、srcに対して単一のfstatを実行し、値を再利用することをお勧めします。正直に言って、ネイティブのLinuxコピーツールとほぼ同じ数値が得られ、数ミリ秒の数百の最適化が私の目標ではなかったので、それ以上進めませんでした。

17
Dmytro

Windowsの場合、コピーを実行しているOSを使用するだけです。

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

/ K-属性をコピーします。通常、Xcopyは読み取り専用属性をリセットします
/O-ファイルの所有権とACL情報をコピーします。
/X-ファイル監査設定をコピーします(/ Oを意味します)。

5
Michael Burns
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)
1
alphanumeric