In Python, how do I check if a drive exists w/o throwing an error for removable drives?

15,626

Solution 1

Use the ctypes package to access the GetLogicalDrives function. This does not require external libraries such as pywin32, so it's portable, although it is a little clunkier to work with. For example:

import ctypes
import itertools
import os
import string
import platform

def get_available_drives():
    if 'Windows' not in platform.system():
        return []
    drive_bitmask = ctypes.cdll.kernel32.GetLogicalDrives()
    return list(itertools.compress(string.ascii_uppercase,
               map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1])))

itertools.compress was added in Python 2.7 and 3.1; if you need to support <2.7 or <3.1, here's an implementation of that function:

def compress(data, selectors):
    for d, s in zip(data, selectors):
        if s:
            yield d

Solution 2

Here's a way that works both on Windows and Linux, for both Python 2 and 3:

import platform,os
def hasdrive(letter):
    return "Windows" in platform.system() and os.system("vol %s: 2>nul>nul" % (letter)) == 0

Solution 3

If you have the win32file module, you can call GetLogicalDrives():

def does_drive_exist(letter):
    import win32file
    return (win32file.GetLogicalDrives() >> (ord(letter.upper()) - 65) & 1) != 0

Solution 4

To disable the error popup, you need to set the SEM_FAILCRITICALERRORS Windows error flag using pywin:

old_mode = win32api.SetErrorMode(0)
SEM_FAILCRITICALERRORS = 1 # not provided by PyWin, last I checked
win32api.SetErrorMode(old_mode & 1)

This tells Win32 not to show the retry dialog; when an error happens, it's returned to the application immediately.

Note that this is what Python calls are supposed to do. In principle, Python should be setting this flag for you. Unfortunately, since Python may be embedded in another program, it can't change process-wide flags like that, and Win32 has no way to specify this flag in a way that only affects Python and not the rest of the code.

Solution 5

import os

possible_drives_list = [chr(97 + num).upper() for num in range(26)]

for drive in possible_drives_list:
    print(drive + ' exists :' + str(os.path.exists(drive + ':\\')))
Share:
15,626
Sam
Author by

Sam

Senior JavaScript Engineer JavaScript, TypeScript, HTML, CSS, Node, Gulp, C#, Animation

Updated on July 23, 2022

Comments

  • Sam
    Sam almost 2 years

    Here's what I have so far:

    import os.path as op
    for d in map(chr, range(98, 123)): #drives b-z
        if not op.isdir(d + ':/'): continue
    

    The problem is that it pops up a "No Disk" error box in Windows:

    maya.exe - No Disk: There is no disk in the drive. Please insert a disk into drive \Device\Harddisk1\DR1 [Cancel, Try Again, Continue]

    I can't catch the exception because it doesn't actually throw a Python error.

    Apparently, this only happens on removable drives where there is a letter assigned, but no drive inserted.

    Is there a way to get around this issue without specifically telling the script which drives to skip?

    In my scenario, I'm at the school labs where the drive letters change depending on which lab computer I'm at. Also, I have zero security privileges to access disk management.

  • Sam
    Sam over 13 years
    Unfortunately, though I'm testing this on Windows 7, I'm trying to make this script cross-platform. Plus, it looks like the win32api needs a different build depending on what kind of processor you have and I'd have to install every single one of these builds just to make this compatible. Am I wrong?
  • Sam
    Sam over 13 years
    I like this approach; though, I'm looking for a cross-platform way of doing it, because my script will potentially be run on Maya via Windows/Mac/Linux.
  • Frédéric Hamidi
    Frédéric Hamidi over 13 years
    @sfjedi, I'm curious to know how Maya emulates drive letters on Linux :)
  • Sam
    Sam over 13 years
    Good call. I've never developed anything for Linux yet, but I just don't feel comfortable going down a road that's specific to Windows. I know that Maya runs on Linux though, which is why I'm relatively concerned. You bring up a good point though. I need to think more about the directory structure on Linux as well. Actually, I'm specifically trying to identify any flash drives that are plugged in with a "school" folder on the root. That's the actual purpose of this script.
  • Sam
    Sam over 13 years
    BTW, I like how you go above and beyond to answer the real question.
  • Matt Joiner
    Matt Joiner over 13 years
    Ummm... I don't see anything to do with linux there.
  • Sam
    Sam over 13 years
    nonetheless, this is actually extremely helpful for my needs. do you happen to know of a way to suppress the command shell popping up?
  • Adam Rosenfield
    Adam Rosenfield over 13 years
    @sfjedi: See my answer (stackoverflow.com/questions/4188326/…) for a way to do this without a command shell popping up.
  • Sam
    Sam about 13 years
    ah, you're a saint! don't forget to import platform though. also, it's still returning removable drives for which there is no drive inserted. that's actually the problem here is that i can't detect if the drive has a disk loaded or not w/o an error of some kind.
  • Sam
    Sam about 13 years
    Update—Spring semester started this week and I had a chance to test this at school. Everything works well without a hiccup, but I need to try on a couple more machines before I see if it truly works w/o the pop-up.
  • Alexander
    Alexander about 12 years
    Matt Joiner: the function hasdrive works on Linux too (returns False, as Linux doesn't have drive letters)
  • Dylan
    Dylan over 6 years
    I was hoping for some info on what "os.system("vol %s: 2>nul>nul" % (letter)) == 0" actually does. I am having a hard time figuring it out.
  • Alexander
    Alexander over 6 years
    Dylan, vol is a Windows command. os.system in combination with 2>nul>nul runs the command in a silent way, where only the return code is used. If the return code is 0 (== 0) then it worked out. %s is replaced with the drive letter, so that for instance vol c: is being run. The idea is to check if this returns an error or not.
  • The EasyLearn Academy
    The EasyLearn Academy almost 3 years
    this will not work in all OS of different platform
  • Frédéric Hamidi
    Frédéric Hamidi almost 3 years
    @TheEasyLearnAcademy, the question is tagged [windows], so I fail to understand what the problem is. For what it's worth, the accepted answer also targets Windows only.
  • theQuestionMan
    theQuestionMan about 2 years
    You are a legend. Thanks! So much more pythonic.