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

    Binary code representing Python Buffer protocol
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    collections.abc.Buffer: Type Binary Data Safely

    Learn Python collections.abc.Buffer for typing binary data, using memoryview, reducing copies, and handling memory safely.

    Ler mais

    Tempo de leitura: 5 minutos
    03/10/2026
    Developer configuring structured logs with Python LoggerAdapter merge_extra
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    LoggerAdapter merge_extra: Dynamic Log Context

    Learn Python LoggerAdapter merge_extra for combining persistent context and per-call fields in safe structured logs.

    Ler mais

    Tempo de leitura: 5 minutos
    03/10/2026
    Laptop screen with code for TLS analysis using Python ssl keylog_filename
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    ssl keylog_filename: Inspect TLS in Wireshark

    Learn Python ssl keylog_filename to inspect authorized TLS sessions in Wireshark without disabling encryption or certificate validation.

    Ler mais

    Tempo de leitura: 5 minutos
    02/10/2026
    Laptop with code and SQLite database for Python sqlite3 autocommit
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    sqlite3 autocommit: Control Transactions in Python

    Learn Python sqlite3 autocommit for explicit transactions, commits, rollbacks, compatibility, and safer SQLite locking.

    Ler mais

    Tempo de leitura: 5 minutos
    02/10/2026
    Developer working with immutable objects and Python copy.replace
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    copy.replace: Update Immutable Objects in Python

    Learn Python copy.replace to create new object versions with targeted changes, immutable state, validation, and predictable code.

    Ler mais

    Tempo de leitura: 5 minutos
    01/10/2026
    Code and file structure illustrating Python pathlib.Path.info
    Advanced Python
    Foto de perfil de Leandro Hirt da Academify

    pathlib.Path.info: Cached File Metadata

    Learn pathlib.Path.info in Python to classify files with cached metadata, scan directories efficiently, and avoid unnecessary system calls.

    Ler mais

    Tempo de leitura: 6 minutos
    01/10/2026