5

Assume the following directory structure:

A
+-- B
|   +-- C
|   |   +-- D
|   |   |   +-- E

where no directory contains any files (not even invisible ones). Running

os.rmdir("A/B/C/D/E"); os.rmdir("A/B/C/D"); os.rmdir("A/B/C"); os.rmdir("A/B"); os.rmdir("A")

in Python (3.5) yields

OSError: [WinError 145] The directory is not empty: '##'

where ## is either A, B, C or D, but executing each function manually does not produce this exception. I'm aware that there is shutil.rmtree, but the documentation of os.rmdir clearly states

Remove (delete) the directory path. Only works when the directory is empty, otherwise, OSError is raised. In order to remove whole directory trees, shutil.rmtree() can be used.

which doesn't seem to be the case, at least on Windows systems. The only workaround I found so far (excluding shutil.rmtree) is

def rm (dir_path):
    while len(os.listdir(dir_path)) > 0:
        pass # Maybe include timeout here to not lock the program
    os.rmdir(dir_path)

Is this a bug or is os.rmdir supposed to not block until the directory is removed?

EDIT: Looking at the source of os.rmdir (for CPython 3.5 on Windows) we can see that RemoveDirectoryW is used for deletion. The remarks section of the documentation of RemoveDirectoryW states

The RemoveDirectory function marks a directory for deletion on close. Therefore, the directory is not removed until the last handle to the directory is closed.

Even though I tried to make sure that there is no handle to the directory, I think this might actually be the problem (thanks to @armatita for the hint).

Cubi73
  • 1,891
  • 3
  • 31
  • 52
  • Its likely that your OS is [locking](https://en.wikipedia.org/wiki/File_locking#In_Microsoft_Windows) the folder for some reason. Check if there is some process happening at the time you are trying to remove the folder. – armatita Sep 11 '17 at 14:41
  • I created this directory structure on a separat partition where no process randomly goes to, I closed Windows explorer and restarted my console to make sure no handle to these directories are open. – Cubi73 Sep 11 '17 at 14:58
  • 1
    Yes, but you mentioned that running the instructions individually will not produce the error. So likely something is holding one or more of your resources. My bet would be that either windows or one of your software (anti-virus?) is doing something in the meanwhile. There is the possibility of a bug but I do not consider it likely. Take a look, for example, at a question like [this](https://stackoverflow.com/questions/11114492/check-if-a-file-is-not-open-not-used-by-other-process-in-python). – armatita Sep 11 '17 at 15:09
  • Yep, that might actually be the reason. I think that closes this problem for me and I have to fall back to my other solution. (in some "crafted" cases `shutil.rmtree` did the same thing as well) – Cubi73 Sep 11 '17 at 15:13
  • Malware scanners are notoriously bad about this. Their filesystem filter drivers break the synchronous semantics of the directory handle opened by `RemoveDirectory` (i.e. the `NtOpenFile` call uses `FILE_SYNCHRONOUS_IO_NONALERT`). There should be a way for filter drivers to work transparently in this case. – Eryk Sun Sep 12 '17 at 16:43

0 Answers0