Мне нужно было найти бесплатную букву диска на окнах из скрипта python. Свободные стенды не назначаются никакому физически или удаленному устройству.
Я провел некоторое исследование и нашел решение здесь в stackoverflow (не помню точной ссылки):
# for python 2.7
import string
import win32api
def getfreedriveletter():
""" Find first free drive letter """
assigneddrives = win32api.GetLogicalDriveStrings().split('\000')[:-1]
assigneddrives = [item.rstrip(':\\').lower() for item in assigneddrives]
for driveletter in list(string.ascii_lowercase[2:]):
if not driveletter in assigneddrives:
return driveletter.upper() + ':'
Это отлично работает для всех физических дисков и подключенных сетевых дисков. Но не для отключенных в настоящее время дисков. Как я могу получить все используемые буквы диска, а также временные не используемые?
Поскольку я передам найденное письмо внешнему скрипту, который будет запускать букву "суб-/букву" Winshell cmd. Я не должен передавать текущий не смонтированный диск, так как он удалит отображение сетевого диска.
Единственный способ, который я нашел, был результатом использования winshellcmd "net use", чтобы найти недоступные диски.
Вот мое решение, если у вас есть лучший способ, поделитесь им со мной:
# for python 2.7
import string
import win32api
from subprocess import Popen, PIPE
def _getnetdrives():
""" As _getfreedriveletter can not find unconnected network drives
get these drives with shell cmd 'net use' """
callstr = 'net use'
phandle = Popen(callstr, stdout=PIPE)
presult = phandle.communicate()
stdout = presult[0]
# _stderr = presult[1]
networkdriveletters = []
for line in stdout.split('\n'):
if ': ' in line:
networkdriveletters.append(line.split()[1] + '\\')
return networkdriveletters
def getfreedriveletter():
""" Find first free drive letter """
assigneddrives = win32api.GetLogicalDriveStrings().split('\000')[:-1]
assigneddrives = assigneddrives + _getnetdrives()
assigneddrives = [item.rstrip(':\\').lower() for item in assigneddrives]
for driveletter in list(string.ascii_lowercase[2:]): #array starts from 'c' as i dont want a and b drive
if not driveletter in assigneddrives:
return driveletter.upper() + ':'
Создание дочернего процесса относительно дорого, а разбор текстового вывода свободной формы - не самый надежный метод. Вместо этого вы можете использовать PyWin32 для вызова тех же функций API, которые net use
вызовы.
import string
import win32api
import win32wnet
import win32netcon
def get_free_drive():
drives = set(string.ascii_uppercase[2:])
for d in win32api.GetLogicalDriveStrings().split(':\\\x00'):
drives.discard(d)
# Discard persistent network drives, even if not connected.
henum = win32wnet.WNetOpenEnum(win32netcon.RESOURCE_REMEMBERED,
win32netcon.RESOURCETYPE_DISK, 0, None)
while True:
result = win32wnet.WNetEnumResource(henum)
if not result:
break
for r in result:
if len(r.lpLocalName) == 2 and r.lpLocalName[1] == ':':
drives.discard(r.lpLocalName[0])
if drives:
return sorted(drives)[-1] + ':'
Обратите внимание, что эта функция возвращает последнюю доступную букву диска. Обычно назначать сопоставленные и заменяющие диски (например, из net.exe и subst.exe) с конца списка и локальные системные диски с самого начала.
Вышеупомянутое решение уже для меня. Хотите поделиться своими результатами, так как я не смог найти решение для своей проблемы в Stackoverflow.
Не стесняйтесь делиться лучшим или более элегантным ответом.