В Python, как проверить, существует ли диск без выдачи ошибки для съемных дисков? - PullRequest
8 голосов
/ 15 ноября 2010

Вот что у меня есть:

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

Проблема в том, что в Windows появляется сообщение об ошибке «Нет диска»:

maya.exe - НетДиск: в приводе нет диска.Пожалуйста, вставьте диск в дисковод \ Device \ Harddisk1 \ DR1 [Отмена, попробуйте еще раз, продолжить]

Я не могу поймать исключение, потому что на самом деле он не выдает ошибку Python.

По-видимому, это происходит только на съемных дисках, для которых назначена буква, но не вставлен диск.

Есть ли способ обойти эту проблему, не указав скрипт, который пропускает диски?

В моем сценарии я нахожусь в школьных лабораториях, где буквы дисков меняются в зависимости от того, на каком компьютере я работаю.Кроме того, у меня нулевые привилегии безопасности для доступа к управлению дисками.

Ответы [ 5 ]

8 голосов
/ 25 января 2011

Используйте пакет ctypes для доступа к функции GetLogicalDrives.Для этого не требуются внешние библиотеки, такие как pywin32, поэтому он переносим, ​​хотя работать с ним немного сложнее.Например:

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 было добавлено в Python 2.7 и 3.1;если вам нужно поддерживать <2.7 или <3.1, вот реализация этой функции: </p>

def compress(data, selectors):
    for d, s in zip(data, selectors):
        if s:
            yield d
4 голосов
/ 15 ноября 2010

Если у вас есть модуль win32file , вы можете вызвать GetLogicalDrives () :

def does_drive_exist(letter):
    import win32file
    return (win32file.GetLogicalDrives() >> (ord(letter.upper()) - 65) & 1) != 0
4 голосов
/ 24 января 2011

Вот способ, который работает как в Windows, так и в Linux, для Python 2 и 3:

import platform,os
def hasdrive(letter):
    return "Windows" in platform.system() and os.system("vol %s: 2>nul>nul" % (letter)) == 0
3 голосов
/ 15 ноября 2010

Чтобы отключить всплывающее окно с ошибкой, вам нужно установить флаг ошибки SEM_FAILCRITICALERRORS Windows с помощью pywin:

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

Это говорит Win32 не показывать диалог повторных попыток;когда происходит ошибка, она немедленно возвращается приложению.

Обратите внимание, что это то, что Python вызывает, должен .В принципе, Python должен установить этот флаг для вас.К сожалению, поскольку Python может быть встроен в другую программу, он не может изменять подобные флаги всего процесса, и Win32 не может указать этот флаг так, чтобы это влияло только на Python, а не на весь код.

0 голосов
/ 02 марта 2016

Пока приемлем небольшой разбор, это один из способов сделать это без установки win32api и без перебора всех возможных букв дисков.

from subprocess import check_output
def getDriveLetters():
    args = [
        'wmic',
        'logicaldisk',
        'get',
        'caption,description,providername',
        '/format:csv'
    ]
    output = check_output(args)
    results = list()
    for line in  output.split('\n'):
        if line:
            lineSplit = line.split(',')
            if len(lineSplit) == 4 and lineSplit[1][1] == ':':
                results.append(lineSplit[1][0])
    return results

Вы также можете анализировать для определенных типов дисков, напримеркак «Сетевое подключение», чтобы получить список всех подключенных к сети букв дисков, например, добавив and lineSplit[2] == 'Network Connection'.

В качестве альтернативы, вместо возврата списка, вы можете вернуть словарь, где ключи - это буквы дисков и значения.являются unc путями (lineSplit[3]).Или любую другую информацию, которую вы хотите получить от wmic.Чтобы увидеть больше вариантов: wmic logicaldisk get /?

...