Table of Contents

Introduction

A while back, I was working on my mod manager for the new Microsoft Flight Simulator. While testing my mod manager, I ran into a scenario where Python couldn’t delete a mod’s folder with the error: Permission Error: [WinError 5] Access is denied. I thought this was strange as the files were owned by my account, and Python should have had permission to delete them (and I hadn’t had this issue with any other mods). I even tried relaunching the Python process as an administrator, and Python still couldn’t delete it.

Recreation of the error.
Recreation of the error. As you can see boxed in red, the Python process is running with Administrator privileges.

Even weirder, the folder was completely empty (as Python was able to delete all of the contents), yet it couldn’t delete the 0-byte folder itself.

Windows dialog showing folder size.
The folder is completely empty. Deselecting the read-only checkbox does not affect anything.

And to make it still stranger, I could delete this folder fine in File Explorer under my regular user account, just not programmatically.

Solution

Unfortunately, I don’t know enough about the NTFS filesystem and Windows to understand why this is happening, but I did figure out how to fix it. You need to apply the stat.S_IWUSR (write by owner) mode to the folder with os.chmod.

Example of fixing the error.
Example of fixing the error. As you can see boxed in red, the Python process is NOT running with Administrator privileges, yet can now delete the folder.

Here is a very simple implementation for recursively fixing permissions:

 1import shutil, os, stat
 2
 3def fix_perm(folder):
 4    for root, dirs, files in os.walk(folder):
 5        for d in dirs:
 6            # recursively fix directories
 7            os.chmod(os.path.join(root, d), stat.S_IWUSR)
 8        for f in files:
 9            # recursively fix files
10            os.chmod(os.path.join(root, f), stat.S_IWUSR)
11
12def rm_tree_perm(folder, first=True):
13    try:
14        # attempt to delete normally
15        shutil.rmtree(folder)
16    except PermissionError:
17        if first:
18            # if first time, fix permissions and try again
19            fix_perm(folder)
20            rm_tree_perm(folder, first=False)
21        else:
22            # raise error with second failure
23            raise PermissionError

You could also just always try to fix the permissions before attempting to delete the folder. I’m not sure of the performance implications.

If you’d like to see this for yourself, I’ve included a minimum working example of this in a Zip file, below. Just extract the file and inside there will be two 0-byte folders. The folder TEXTURE.REDBULL will have this mysterious issue and the folder TEXTURE.YELLOW will not.

Asobo_E330.zip