1. ホーム
  2. python

Windows で shutil.rmtree が 'Access is denied' で失敗する [duplicate] 。

2023-08-17 15:20:23

質問

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インストール上で実行することを目標としているので)。

どのように解決するのですか?

この質問をチェックしてください。 pythonのスクリプトはWindowsでどんなユーザーとして動くか。

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

ここで onerror() のハンドラです。 pathutils.py というハンドラで、@Sridhar Ratnakumar がコメントで言及しています。

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
    # Is the error an access error?
    if not os.access(path, os.W_OK):
        os.chmod(path, stat.S_IWUSR)
        func(path)
    else:
        raise