代码之家  ›  专栏  ›  技术社区  ›  Sridhar Ratnakumar

Shutil.rmtree在具有“访问被拒绝”的Windows上失败

  •  57
  • Sridhar Ratnakumar  · 技术社区  · 14 年前

    在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/ 但在窗户上呢?(不必使用第三方工具,如unxutils或cygwin,因为这段代码的目标是在安装了python 2.6w/pywin32的裸windows安装上运行)

    5 回复  |  直到 8 年前
        1
  •  72
  •   Community CDub    7 年前

    看看这个问题:

    What user do python scripts run as in 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
        if not os.access(path, os.W_OK):
            # Is the error an access error ?
            os.chmod(path, stat.S_IWUSR)
            func(path)
        else:
            raise
    
        2
  •  22
  •   ubershmekel    9 年前

    我会说实现你自己的rmtree os.walk 通过使用 os.chmod 在尝试删除每个文件之前。

    类似这样的东西(未经测试):

    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)      
    
        3
  •  10
  •   HHest balpha    8 年前

    好吧,有标记的解决方案对我不起作用…而是这样做了:

    os.system('rmdir /S /Q "{}"'.format(directory))
    
        4
  •  0
  •   RY_ Zheng    10 年前
    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, 路径,exc_info),其中func是os.listdir、os.remove或os.rmdir; path是导致函数失败的参数;以及 exc_info是sys.exc_info()返回的元组。如果忽略错误 为false,onerror为none,则引发异常。请在此处输入代码

        5
  •  -2
  •   besil    9 年前

    一个简单的解决方法是 subprocess.call

    from subprocess import call
    call("rm -rf build/", shell=True)
    

    为了执行你想要的一切。