44

I'm trying to have python delete some directories and I get access errors on them. I think its that the python user account doesn't have rights?

WindowsError: [Error 5] Access is denied: 'path'

is what I get when I run the script.
I've tried

shutil.rmtree  
os.remove  
os.rmdir

they all return the same error.

DevelopingChris
  • 39,797
  • 30
  • 87
  • 118
  • Well, with which user account *do* you run the script? Usually you should know, at least on your machines and if you set up the script to run ... – Joey Jul 31 '09 at 17:03
  • I'm just running it as myself, and I can delete the directly manually, so I'm thinking its a weird windows and python permissions disconnect – DevelopingChris Jul 31 '09 at 17:04
  • Try running the script with SysInternals' "Process Monitor" to see exactly which object (file, directory or whatever) the error occurs on and what process it occurs in. "Process Explorer" can tell you what crededtials the process is running under (maybe Process Monitor can too; I'm not sure). – Michael Burr Jul 31 '09 at 17:21
  • Would you mind printing out the path you're trying to delete and posting the output here? It could be a problem with the format the path is specified in. – Andre Miller Jul 31 '09 at 19:39

7 Answers7

86

We've had issues removing files and directories on Windows, even if we had just copied them, if they were set to 'readonly'. shutil.rmtree() offers you sort of exception handlers to handle this situation. You call it and provide an exception handler like this:

import errno, os, stat, shutil

def handleRemoveReadonly(func, path, exc):
  excvalue = exc[1]
  if func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES:
      os.chmod(path, stat.S_IRWXU| stat.S_IRWXG| stat.S_IRWXO) # 0777
      func(path)
  else:
      raise

shutil.rmtree(filename, ignore_errors=False, onerror=handleRemoveReadonly)

You might want to try that.

pradyunsg
  • 18,287
  • 11
  • 43
  • 96
ThomasH
  • 22,276
  • 13
  • 61
  • 62
  • 2
    Also see the `onerror` function in http://www.voidspace.org.uk/downloads/pathutils.py – Sridhar Ratnakumar Apr 16 '10 at 22:31
  • I'm getting: NameError: name 'stat' is not defined EDIT: Requires that you do 'import stat' at the top of your script. Did solve my problem though. Many thanks! – fIwJlxSzApHEZIl Apr 04 '12 at 19:19
  • 3
    I tried this solution, now I have the `[Error 5] Access denied` error with this line : `os.chmod(path, stat.S_IRWXU| stat.S_IRWXG| stat.S_IRWXO) # 0777 ` – Johanna May 10 '12 at 15:22
  • @Johanna This recipe only works for files for which you have chmod permission (e.g. files you own). – ThomasH May 11 '12 at 20:11
  • It's also necessary to import errno – User May 12 '12 at 13:41
  • 4
    Use `func in (os.rmdir, os.unlink, os.remove)`, especially as of python 3.7. I couldn't find where `os.remove` is passed to the error handler anywhere as of 3.7. "This function is semantically identical to `remove()`" - [python os.unlink](https://docs.python.org/3/library/os.html?highlight=unlink#os.unlink) – Quinn Dirks Jan 01 '19 at 11:53
  • 1
    @QuinnDirks Yes, this is all python 2.x. Check the appropriate docs for `shutil.rmtree` and maybe play a bit with it. It all hinges on the function that `shutil.rmtree` passes into the error handler, the one which failed (which, as the docs say, is platform- and implementaton-dependent). Maybe you want to print out the passed function in the error handler, so you see which function is being used in your environment and your use case. – ThomasH Jan 02 '19 at 10:03
2

I've never used Python, but I would assume it runs as whatever user executes the script.

Max Schmeling
  • 12,363
  • 14
  • 66
  • 109
  • ok, so it apparently runs as me, why can't I delete the file through python, but I can if I just delete it through rmdir on the command line? – DevelopingChris Jul 31 '09 at 17:14
  • Do you just have the path hard coded? Are you sure it's the correct path? I can't think of any reason why it wouldn't work if you can do it manually. – Max Schmeling Jul 31 '09 at 17:16
  • yeah, I had it dynamically getting the path from a listdir, but then when that got hosed up, I just put the same path in python, setup the scenario and python can't delete it but I can if I use cmd – DevelopingChris Jul 31 '09 at 17:27
  • I really don't know what could be the issue then. I'm guessing the Access denied error is just disguising the real issue, unless Python runs methods like that in some kind of sandbox. Sorry I don't have better answers. – Max Schmeling Jul 31 '09 at 17:59
2

The scripts have no special user, they just run under the currently logged-in user which executed the script.

Have you tried checking that:

  • you are trying to delete a valid path? and that
  • the path has no locked files?
Yuval Adam
  • 161,610
  • 92
  • 305
  • 395
0

How are you running the script? From an interactive console session? If so, just open up a DOS command window (using cmd) and type 'whoami'. That is who you are running the scripts interactively.

Ok I saw your edits just now...why don't you print the path and check the properties to see if the user account running the scripts has the required privileges?

If whoami does not work on your version of Windows, you may use the environment variables like SET USERNAME and SET DOMAINNAME from your command window.

msvcyc
  • 2,569
  • 4
  • 24
  • 30
  • 1
    whoami is a *nix command, not windows. – Max Schmeling Jul 31 '09 at 17:06
  • 2
    @Max--have you tried it on Windows? It works just fine. – Kevin Jul 31 '09 at 17:07
  • 1
    I just tried it, it doesn't work for me – Max Schmeling Jul 31 '09 at 17:07
  • 1
    `whoami` not found on my XP at work. – Mark Rushakoff Jul 31 '09 at 17:09
  • I'm guessing something you've installed added a whoami command. – Max Schmeling Jul 31 '09 at 17:09
  • whoami comes with the gnu port, so does ls, its the only thing that makes cmd bearable – DevelopingChris Jul 31 '09 at 17:10
  • @Max: whoami works fine on my version of WIndows which is 2003 server. what version of windows are u running? Don't just provide a blanket comment saying it is a *NIX command and do not down vote if you are not sure about something. Please ask the community. – msvcyc Jul 31 '09 at 17:10
  • btw, whoami, says me, but I can manually delete the directory with rmdir /S, why can't python? – DevelopingChris Jul 31 '09 at 17:11
  • @msvcyc Are you running 'whoami' in cmd or in powershell? – Max Schmeling Jul 31 '09 at 17:19
  • FWIW, my WinXP Pro x4 setup have a whoami.exe in SYSTEM32 that's copyright by Microsoft. I honestly can't say if it's a default part of the system or some ther toolset installed it (maybe a resource kit or something). I doubt it's a default part of the system, since I know I often try to use it on systems where it's not found (which is pretty irritating). – Michael Burr Jul 31 '09 at 17:19
  • Provide a ****** reason before down voting. That way I'll also learn if I am wrong. – msvcyc Jul 31 '09 at 17:21
  • @Max: whoami is available by default in vista, 2k8 and is part of service packs in 2000, 2003 and possibly XP pro (I am not sure) – msvcyc Jul 31 '09 at 17:24
  • @msvcyc: XP pro doesn't have whoami command unless you install external tools like cygwin or something. – codingbear Jul 31 '09 at 17:47
  • For what its worth, whoami is standard on at least Vista and Windows 7. Although, its almost as easy to just type ECHO %USERDOMAIN%\%USERNAME% to get the same output on other Windows versions. – Andre Miller Jul 31 '09 at 19:36
-1

If the script is being run as a scheduled task (which seems likely for a cleanup script), it will probably run as SYSTEM. It's (unwise, but) possible to set permissions on directories so that SYSTEM has no access.

pzr
  • 1,226
  • 9
  • 6
  • Scheduled tasks run as whatever user you tell it to run as. Though, I think on older versions of windows this isn't true. – Max Schmeling Jul 31 '09 at 17:10
-1

@ThomasH : another brick to the wall.

On unix systems, you have to ensure that parent directory is writeable too. Here is another version :

def remove_readonly(func, path, exc):
    excvalue = exc[1]
    if func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES:

        # ensure parent directory is writeable too
        pardir = os.path.abspath(os.path.join(path, os.path.pardir))
        if not os.access(pardir, os.W_OK):
            os.chmod(pardir, stat.S_IRWXU| stat.S_IRWXG| stat.S_IRWXO)

        os.chmod(path, stat.S_IRWXU| stat.S_IRWXG| stat.S_IRWXO) # 0777
        func(path)
    else:
        raise
fylb
  • 679
  • 4
  • 10
  • According to the [Python Documention](https://docs.python.org/2/library/shutil.html?highlight=shutil#shutil.rmtree), _Exceptions raised by onerror will not be caught_ so I'm not sure the _raise_ statement means anything. – kmarsh Nov 03 '15 at 16:31
-3

Simple solution after searching for hours is to check first if that folder actually exist!

GIT_DIR="C:/Users/...."
if os.path.exists(GIT_DIR):
    shutil.rmtree(GIT_DIR)

This did the trick for me.

Nerminz
  • 27
  • 6
  • The difference is, I just created it in the previous line of code. So it 100% exists for certain. But there is an access problem in the OS level adapters of windows. – DevelopingChris Jan 29 '18 at 01:29