5

Python でディレクトリを削除する方法を確認したところ、shutil.rmtree()を使用するようになりました。私が期待していたものと比較して、その速度は私を驚かせましたrm --recursiveサブプロセスモジュールを使用する以外に、より高速な代替手段はありますか?

4

3 に答える 3

9

実装は多くの追加処理を行います。

def rmtree(path, ignore_errors=False, onerror=None):
    """Recursively delete a directory tree.

    If ignore_errors is set, errors are ignored; otherwise, if onerror
    is set, it is called to handle the error with arguments (func,
    path, exc_info) where func is os.listdir, os.remove, or os.rmdir;
    path is the argument to that function that caused it to fail; and
    exc_info is a tuple returned by sys.exc_info(). If ignore_errors
    is false and onerror is None, an exception is raised.

    """
    if ignore_errors:
         def onerror(*args):
              pass
    elif onerror is None:
         def onerror(*args):
              raise
    try:
         if os.path.islink(path):
              # symlinks to directories are forbidden, see bug #1669
              raise OSError("Cannot call rmtree on a symbolic link")
    except OSError:
         onerror(os.path.islink, path, sys.exc_info())
         # can't continue even if onerror hook returns
         return
    names = []
    try:
         names = os.listdir(path)
    except os.error, err:
         onerror(os.listdir, path, sys.exc_info())
    for name in names:
         fullname = os.path.join(path, name)
         try:
              mode = os.lstat(fullname).st_mode
         except os.error:
              mode = 0
         if stat.S_ISDIR(mode):
              rmtree(fullname, ignore_errors, onerror)
         else:
             try:
                 os.remove(fullname)
             except os.error, err:
                 onerror(os.remove, fullname, sys.exc_info())
    try:
         os.rmdir(path)
    except os.error:
         onerror(os.rmdir, path, sys.exc_info()) 

os.path.join()新しいファイル名の作成に使用されることに注意してください。文字列操作には時間がかかります。代わりに、rm(1)実装はunlinkat(2)システムコールを使用しますが、これは追加の文字列操作を行いません。namei()(実際、カーネルは、共通のディレクトリを見つけるためだけに全体を何度も何度も歩く必要がありません。カーネルのdentryキャッシュは優れていて便利ですが、それでもかなりの量のカーネル内文字列操作になる可能性があります。ユーティリティrm(1)は、そのすべての文字列操作をバイパスし、ディレクトリのファイル記述子を使用するだけです。

さらに、ツリー内のすべてのファイルとディレクトリの両方rm(1)rmtree()チェックします。ただし、Cの実装では、単純な整数マスク操作を実行するためだけに、すべてをPythonオブジェクトに変換するst_mode必要はありません。struct statbufこのプロセスにかかる時間はわかりませんが、ディレクトリツリー内のすべてのファイル、ディレクトリ、パイプ、シンボリックリンクなどで1回発生します。

于 2011-03-29T10:44:11.290 に答える
2

速度を重視する場合:

os.system('rm -fr "%s"' % your_dirname)

それとは別に、 shutil.rmtree() がはるかに遅いとは思いませんでした...もちろん、関係するPythonレベルには余分なオーバーヘッドがあります。それとは別に、あなたが合理的な数字を提供した場合にのみ、私はそのような主張を信じます.

于 2011-03-29T10:20:12.007 に答える
1

何が問題なのかわかりませんが、他の方法を試すことができます。たとえば、すべてのファイルを削除してからディレクトリを試してください。

for r,d,f in os.walk("path"):
   for files in f:
       os.remove ( os.path.join(r,files) )
   os.removedirs( r ) 
于 2011-03-29T10:44:34.093 に答える