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)
次のコードで取得したコードを最適化しなかった最速バージョン:
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コピーツールとほぼ同じ数値が得られ、数ミリ秒の数百の最適化が私の目標ではなかったので、それ以上進めませんでした。
Windowsの場合、コピーを実行しているOSを使用するだけです。
from subprocess import call
call(["xcopy", "c:\\file.txt", "n:\\folder\\", "/K/O/X"])
/ K-属性をコピーします。通常、Xcopyは読み取り専用属性をリセットします
/O-ファイルの所有権とACL情報をコピーします。
/X-ファイル監査設定をコピーします(/ 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)