os.listdrives: List Windows Drives in Python

Published on: October 4, 2026
Reading time: 4 minutes
Developer working on Windows drive automation with Python

Windows applications often need to discover which drives are available before searching for files, creating backups, or presenting storage choices. Python provides os.listdrives(), a dedicated function that returns the roots of the drives currently known to the system.

This avoids fragile loops over letters from A to Z, shell commands, and third-party dependencies. This guide explains the return value, platform checks, integration with pathlib, removable and network drives, free-space checks, path validation, testing, and safe automation patterns.

What os.listdrives returns

The function returns a list of strings representing absolute drive roots. A typical result may contain C:\, D:\, and letters assigned to partitions, USB devices, optical drives, or mapped network locations.

import os
for drive in os.listdrives():
    print(drive)

Being present in the list does not guarantee successful access. A removable device may be ejected, a network drive may be disconnected, and permissions may deny reading.

Platform availability

os.listdrives() is Windows-specific. Cross-platform code should check the operating system before calling it.

import os
import sys

if sys.platform == "win32":
    roots = os.listdrives()
else:
    roots = ["/"]

This keeps platform-specific logic isolated. Linux and macOS use mount points rather than Windows drive letters.

Converting roots to Path objects

pathlib.Path makes path composition and inspection easier.

from pathlib import Path
import os

roots = [Path(value) for value in os.listdrives()]
for root in roots:
    print(root, root.exists())

Rechecking availability is useful because device state can change between discovery and access.

Checking free space

Backup tools commonly need available capacity. Combine the roots with shutil.disk_usage().

import os
import shutil

for root in os.listdrives():
    try:
        total, used, free = shutil.disk_usage(root)
    except OSError as error:
        print(root, "unavailable:", error)
        continue
    print(root, free // (1024 ** 3), "GB free")

Handling OSError is essential for removable media, empty readers, and unstable network mappings.

Removable media

A USB drive can disappear after the list is created. Do not cache drive results indefinitely when external devices matter. Refresh the list before opening a selector or starting an important operation.

Do not assume a removable device always receives the same letter. Windows may assign a different root on a later connection.

Network drives

Mapped network drives may appear with local disks. They can require credentials, add latency, or become temporarily unreachable. Code that scans every root should tolerate failures and let users exclude slow destinations.

UNC locations such as \\server\share may not appear unless mapped to a letter. Therefore, listdrives() does not replace explicit configuration of known network shares.

Filtering accessible roots

from pathlib import Path
import os

def accessible_roots():
    result = []
    for value in os.listdrives():
        root = Path(value)
        try:
            next(root.iterdir(), None)
        except (OSError, PermissionError):
            continue
        result.append(root)
    return result

Listing a directory can be expensive on some devices, so perform this check only when access confirmation is necessary.

Looking for a known file or folder

When the relative path is known, test the direct candidate instead of recursively scanning entire disks.

from pathlib import Path
import os

def find_at_roots(name):
    found = []
    for value in os.listdrives():
        candidate = Path(value) / name
        try:
            if candidate.exists():
                found.append(candidate)
        except OSError:
            pass
    return found

For broad searches, add depth limits, filters, progress reporting, and cancellation.

Validating user-supplied paths

Never trust text concatenation for destructive operations. Resolve the destination and confirm that it remains inside an allowed root.

from pathlib import Path

def inside_root(root, relative):
    base = Path(root).resolve()
    destination = (base / relative).resolve()
    return destination == base or base in destination.parents

Require extra confirmation before deleting or overwriting data, and never let an empty relative value accidentally target the whole drive.

Building a drive selector

import os

drives = os.listdrives()
for index, drive in enumerate(drives, start=1):
    print(f"{index}. {drive}")

Validate the selected index and refresh the list before a long operation because the underlying devices may have changed.

Error handling

Typical exceptions include OSError, PermissionError, and FileNotFoundError. Record which root failed and continue with other drives when that is safe. User-facing applications should explain whether the problem involves permissions, disconnected storage, or missing media.

Testing

Tests should not depend on the real letters of the machine running them. Wrap discovery in a function and inject a fake provider.

def choose_roots(list_roots):
    return [root for root in list_roots() if root]

Tests can then cover an empty list, one drive, inaccessible drives, duplicates, and changes between calls without touching real storage.

When not to use os.listdrives

If the program already receives a configured directory, scanning every drive is unnecessary. For known user folders, prefer environment variables and platform APIs. On Linux servers, work with mount points instead of trying to reproduce Windows drive semantics.

Read the Academify guides about the os module, pathlib, large files, and exception handling. The official os documentation and shutil documentation provide the API details.

Best practices

Refresh the list before important work, handle failures per drive, avoid fixed-letter assumptions, limit searches, and validate external paths. Keep Windows-specific code inside a small, testable function in cross-platform projects.

Conclusion

os.listdrives() provides a direct, standard way to discover Windows drives. Combined with pathlib, shutil, validation, and careful exception handling, it supports reliable storage selectors, backup utilities, and file automation. Treat the result as a temporary snapshot: devices, networks, and permissions can change between calls, so every important access still needs verification.

Share:

Facebook
WhatsApp
Twitter
LinkedIn

Article content

    Related articles

    Code on a screen representing Python t-strings
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    Python 3.14 T-strings: Structured Templates

    Learn Python t-strings in Python 3.14, inspect Template and Interpolation objects, and build structured, extensible renderers.

    Ler mais

    Tempo de leitura: 5 minutos
    16/10/2026
    CPU and memory modules representing Python shared_memory track
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    shared_memory track: Control the Resource Tracker

    Learn Python shared_memory track for safe resource tracking, ownership, cleanup, and independent process coordination.

    Ler mais

    Tempo de leitura: 5 minutos
    16/10/2026
    Data storage unit representing compression with Python compression.zstd
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    compression.zstd: Streaming and Safe Compression

    Learn Python compression.zstd for fast file and data compression with streaming, dictionaries, testing, and safe limits.

    Ler mais

    Tempo de leitura: 6 minutos
    15/10/2026
    Code on screen for diagnosing processes with Python sys.remote_exec
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    sys.remote_exec: Diagnose Running Python Processes

    Learn Python sys.remote_exec for diagnosing running processes with controlled scripts, strong permissions, and safe operational practices.

    Ler mais

    Tempo de leitura: 6 minutos
    15/10/2026
    Python code and environment configuration with os.reload_environ
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    os.reload_environ: Thread Safety and Environment

    Learn Python os.reload_environ to refresh externally changed environment variables with validation, compatibility, and thread-safety precautions.

    Ler mais

    Tempo de leitura: 4 minutos
    14/10/2026
    Python code representing contextvars.Token and asynchronous context isolation
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    contextvars.Token: Restore Async Context Safely

    Learn Python contextvars.Token for temporary values, automatic restoration, and safe context isolation across asynchronous tasks.

    Ler mais

    Tempo de leitura: 6 minutos
    14/10/2026