web-dev-qa-db-ja.com

shutil.rmtreeがWindowsで「アクセスが拒否されました」と失敗する

Pythonでは、shutil.rmtree読み取り専用ファイルを含むフォルダー上では、次の例外が出力されます。

 File "C:\Python26\lib\shutil.py", line 216, in rmtree
   rmtree(fullname, ignore_errors, onerror)
 File "C:\Python26\lib\shutil.py", line 216, in rmtree
   rmtree(fullname, ignore_errors, onerror)
 File "C:\Python26\lib\shutil.py", line 216, in rmtree
   rmtree(fullname, ignore_errors, onerror)
 File "C:\Python26\lib\shutil.py", line 216, in rmtree
   rmtree(fullname, ignore_errors, onerror)
 File "C:\Python26\lib\shutil.py", line 216, in rmtree
   rmtree(fullname, ignore_errors, onerror)
 File "C:\Python26\lib\shutil.py", line 216, in rmtree
   rmtree(fullname, ignore_errors, onerror)
 File "C:\Python26\lib\shutil.py", line 216, in rmtree
   rmtree(fullname, ignore_errors, onerror)
 File "C:\Python26\lib\shutil.py", line 221, in rmtree
   onerror(os.remove, fullname, sys.exc_info())
 File "C:\Python26\lib\shutil.py", line 219, in rmtree
   os.remove(fullname)
WindowsError: [Error 5] Access is denied: 'build\\tcl\\tcl8.5\\msgs\\af.msg'

[ファイルのプロパティ]ダイアログを見ると、af.msgファイルは読み取り専用に設定されます。

したがって、問題は:最も単純なこの問題を回避するための回避策/修正とは何ですか-私の意図はrm -rf build/しかし、Windows上で? (unxutilsやcygwinなどのサードパーティ製ツールを使用する必要はありません-このコードは、Python 2.6 w/PyWin32がインストールされた裸のWindowsインストールで実行されることを目的としています)

62

この質問をチェックしてください:

ユーザーが行うことpythonスクリプトはWindowsで実行されますか?

どうやらその答えは、ファイル/フォルダを読み取り専用に変更してから削除することです。

これは、コメントで@Sridhar Ratnakumarが言及した _pathutils.py_onerror()ハンドラーです。

_def onerror(func, path, exc_info):
    """
    Error handler for ``shutil.rmtree``.

    If the error is due to an access error (read only file)
    it attempts to add write permission and then retries.

    If the error is for another reason it re-raises the error.

    Usage : ``shutil.rmtree(path, onerror=onerror)``
    """
    import stat
    if not os.access(path, os.W_OK):
        # Is the error an access error ?
        os.chmod(path, stat.S_IWUSR)
        func(path)
    else:
        raise
_
78
Justin Peel

削除を試みる前に各ファイルで os.chmod を使用してアクセスを保証する os.walk で独自のrmtreeを実装するとします。

このようなもの(未テスト):

import os
import stat

def rmtree(top):
    for root, dirs, files in os.walk(top, topdown=False):
        for name in files:
            filename = os.path.join(root, name)
            os.chmod(filename, stat.S_IWUSR)
            os.remove(filename)
        for name in dirs:
            os.rmdir(os.path.join(root, name))
    os.rmdir(top)      
24
Epcylon

さて、マークされたソリューションは私のために機能しませんでした...代わりにこれをしました:

os.system('rmdir /S /Q "{}"'.format(directory))
14
AlexeiOst
shutil.rmtree(path,ignore_errors=False,onerror=errorRemoveReadonly) 
def errorRemoveReadonly(func, path, exc):
    excvalue = exc[1]
    if func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES:
        # change the file to be readable,writable,executable: 0777
        os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)  
        # retry
        func(path)
    else:
        raiseenter code here

Ignore_errorsが設定されている場合、エラーは無視されます。それ以外の場合、onerrorが設定されていると、引数(func、path、exc_info)を使用してエラーを処理するために呼び出されます。funcはos.listdir、os.remove、またはos.rmdirです。 pathは、失敗する原因となったその関数の引数です。 exc_infoは、sys.exc_info()によって返されるTupleです。 ignore_errorsがfalseでonerrorがNoneの場合、例外が発生します。ここにコードを入力してください

0
RongyanZheng