ZetCode

Python os.rmdir Function

Last modified April 11, 2025

This comprehensive guide explores Python's os.rmdir function, which removes empty directories. We'll cover basic usage, error handling, path specifications, and practical examples.

Basic Definitions

The os.rmdir function removes an empty directory specified by path. It's part of Python's os module for operating system interactions.

Key parameters: path (directory to remove). Raises OSError if directory isn't empty or if permissions prevent removal. Works across platforms.

Removing an Empty Directory

The simplest use of os.rmdir removes an empty directory. This example shows basic usage with proper error handling.

basic_removal.py
import os

# Directory to remove
dir_path = "empty_dir"

try:
    os.rmdir(dir_path)
    print(f"Successfully removed {dir_path}")
except FileNotFoundError:
    print(f"Directory {dir_path} does not exist")
except OSError as e:
    print(f"Error removing {dir_path}: {e}")

This attempts to remove a directory and handles common errors. The OSError catches cases where the directory isn't empty or lacks permissions.

Always use try/except with os.rmdir as multiple things can go wrong during directory removal operations.

Checking Directory Empty Before Removal

We can verify a directory is empty before attempting removal using os.listdir. This provides better error messages.

check_empty.py
import os

dir_path = "test_dir"

try:
    if not os.listdir(dir_path):
        os.rmdir(dir_path)
        print(f"Removed empty directory {dir_path}")
    else:
        print(f"Directory {dir_path} is not empty")
except FileNotFoundError:
    print(f"Directory {dir_path} does not exist")
except PermissionError:
    print(f"No permission to access {dir_path}")

This first checks if the directory is empty using os.listdir. Only if empty does it attempt removal. This provides more specific feedback to users.

Note there's still a race condition between checking and removal - files could be added by another process in between.

Removing Directories with Relative Paths

os.rmdir works with relative paths. This example demonstrates removing directories using different relative path notations.

relative_paths.py
import os

# Create some test directories
os.makedirs("dir1/dir2/dir3", exist_ok=True)

# Remove using different relative paths
try:
    os.rmdir("dir1/dir2/dir3")  # Relative from current
    os.rmdir("./dir1/dir2")      # Using ./ notation
    os.rmdir("../relative_paths.py/dir1")  # Using .. notation
except OSError as e:
    print(f"Error removing directory: {e}")

# Clean up remaining directories
os.removedirs("dir1")  # Removes all empty parents

This shows how different relative path notations work with os.rmdir. The example also demonstrates using os.removedirs for recursive cleanup.

Relative paths are resolved based on the current working directory, which can be checked with os.getcwd().

Removing Directories with Absolute Paths

For more reliable operations, absolute paths can be used. This example shows how to construct and use absolute paths with os.rmdir.

absolute_paths.py
import os

# Create test directory structure
base_dir = os.path.abspath("test_dirs")
os.makedirs(os.path.join(base_dir, "subdir"), exist_ok=True)

# Remove using absolute paths
try:
    subdir_path = os.path.join(base_dir, "subdir")
    if os.path.exists(subdir_path):
        os.rmdir(subdir_path)
        print(f"Removed {subdir_path}")
    
    # Try to remove base (will fail if not empty)
    os.rmdir(base_dir)
except OSError as e:
    print(f"Error: {e}")

# Clean up
if os.path.exists(base_dir) and not os.listdir(base_dir):
    os.rmdir(base_dir)

This constructs absolute paths using os.path.abspath and os.path.join for reliable path handling across platforms. The operations are more predictable.

Absolute paths eliminate dependency on current working directory but require proper path construction to be portable.

Error Handling and Different Exception Types

os.rmdir can raise several exception types. This example shows how to handle each case appropriately.

error_handling.py
import os
import errno

def remove_directory(path):
    try:
        os.rmdir(path)
        print(f"Successfully removed {path}")
    except FileNotFoundError:
        print(f"Directory {path} does not exist")
    except PermissionError:
        print(f"Permission denied for {path}")
    except OSError as e:
        if e.errno == errno.ENOTEMPTY:
            print(f"Directory {path} is not empty")
        elif e.errno == errno.ENOENT:
            print(f"Path {path} does not exist")
        else:
            print(f"Error removing {path}: {e}")

# Test cases
remove_directory("nonexistent_dir")      # FileNotFoundError
remove_directory("/root/protected_dir")  # PermissionError
os.makedirs("not_empty_dir", exist_ok=True)
with open("not_empty_dir/file.txt", "w") as f:
    f.write("test")
remove_directory("not_empty_dir")        # ENOTEMPTY

This demonstrates comprehensive error handling for os.rmdir. Different exception types provide specific information about what went wrong.

The errno module helps identify specific error conditions for more precise error messages and recovery attempts.

Platform-Specific Behavior

os.rmdir behavior can vary between operating systems. This example highlights key differences between Unix and Windows.

platform_differences.py
import os
import sys

def platform_specific_removal():
    test_dir = "test_dir"
    os.makedirs(test_dir, exist_ok=True)
    
    try:
        # Attempt to remove with open file (behavior differs)
        with open(os.path.join(test_dir, "temp.txt"), "w") as f:
            f.write("data")
            if sys.platform == "win32":
                print("Windows: Trying to remove directory with open file")
                os.rmdir(test_dir)
            else:
                print("Unix: Trying to remove directory with open file")
                os.rmdir(test_dir)
    except OSError as e:
        print(f"Expected error: {e}")
    finally:
        # Cleanup
        if os.path.exists(test_dir):
            for file in os.listdir(test_dir):
                os.remove(os.path.join(test_dir, file))
            os.rmdir(test_dir)

platform_specific_removal()

This shows how Windows and Unix handle directory removal differently, particularly when files are open. Windows often locks directories in use.

Always test directory operations on your target platform and handle platform-specific cases appropriately in production code.

Using os.rmdir in a Context Manager

We can create a context manager for safer directory removal that handles cleanup automatically. This demonstrates advanced usage.

context_manager.py
import os
import contextlib

@contextlib.contextmanager
def temporary_directory(path):
    """Context manager for a temporary directory that gets removed"""
    os.makedirs(path, exist_ok=True)
    try:
        yield path
    finally:
        try:
            # Remove all contents first
            for entry in os.listdir(path):
                full_path = os.path.join(path, entry)
                if os.path.isdir(full_path):
                    os.rmdir(full_path)
                else:
                    os.unlink(full_path)
            os.rmdir(path)
        except OSError as e:
            print(f"Warning: Could not remove {path}: {e}")

# Usage example
with temporary_directory("temp_data") as temp_dir:
    print(f"Working in {temp_dir}")
    with open(os.path.join(temp_dir, "log.txt"), "w") as f:
        f.write("Temporary data")
    # Directory automatically removed when block exits

This creates a reusable context manager for temporary directories. The directory and contents are automatically removed when the with block exits.

The context manager handles cleanup even if exceptions occur, making it safer than manual removal in many cases.

Security Considerations

Best Practices

Source References

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Python tutorials.