¿Hay una manera de enumerar todas las letras de unidad disponibles en python?

Más o menos lo que dice en la lata: ¿hay una manera (fácil) en Python de enumerar todas las letras de unidad actualmente en uso en un sistema de Windows?

(Parece que mi google-fu me ha decepcionado en este caso).

Relacionado:

  • Enumerar todas las letras de unidad disponibles en Windows (C ++ / Win32)

Related of "¿Hay una manera de enumerar todas las letras de unidad disponibles en python?"

import win32api drives = win32api.GetLogicalDriveStrings() drives = drives.split('\000')[:-1] print drives 

Adaptado de: http://www.faqts.com/knowledge_base/view.phtml/aid/4670

Sin usar ninguna biblioteca externa, si eso te importa:

 import string from ctypes import windll def get_drives(): drives = [] bitmask = windll.kernel32.GetLogicalDrives() for letter in string.uppercase: if bitmask & 1: drives.append(letter) bitmask >>= 1 return drives if __name__ == '__main__': print get_drives() # On my PC, this prints ['A', 'C', 'D', 'F', 'H'] 

Esas parecen mejores respuestas. Aquí está mi truco pirata

 import os, re re.findall(r"[AZ]+:.*$",os.popen("mountvol /").read(),re.MULTILINE) 

Riffing un poco en la respuesta de RichieHindle ; no es realmente mejor, pero puedes hacer que Windows haga el trabajo de crear letras reales del alfabeto

 >>> import ctypes >>> buff_size = ctypes.windll.kernel32.GetLogicalDriveStringsW(0,None) >>> buff = ctypes.create_string_buffer(buff_size*2) >>> ctypes.windll.kernel32.GetLogicalDriveStringsW(buff_size,buff) 8 >>> filter(None, buff.raw.decode('utf-16-le').split(u'\0')) [u'C:\\', u'D:\\'] 

El repository de Microsoft Script incluye esta receta que podría ayudar. Sin embargo, no tengo una máquina con Windows para probarlo, así que no estoy seguro de si quieres “Nombre”, “Nombre del sistema”, “Nombre del volumen” o tal vez algo más.

 import win32com.client strComputer = "." objWMIService = win32com.client.Dispatch("WbemScripting.SWbemLocator") objSWbemServices = objWMIService.ConnectServer(strComputer,"root\cimv2") colItems = objSWbemServices.ExecQuery("Select * from Win32_LogicalDisk") for objItem in colItems: print "Access: ", objItem.Access print "Availability: ", objItem.Availability print "Block Size: ", objItem.BlockSize print "Caption: ", objItem.Caption print "Compressed: ", objItem.Compressed print "Config Manager Error Code: ", objItem.ConfigManagerErrorCode print "Config Manager User Config: ", objItem.ConfigManagerUserConfig print "Creation Class Name: ", objItem.CreationClassName print "Description: ", objItem.Description print "Device ID: ", objItem.DeviceID print "Drive Type: ", objItem.DriveType print "Error Cleared: ", objItem.ErrorCleared print "Error Description: ", objItem.ErrorDescription print "Error Methodology: ", objItem.ErrorMethodology print "File System: ", objItem.FileSystem print "Free Space: ", objItem.FreeSpace print "Install Date: ", objItem.InstallDate print "Last Error Code: ", objItem.LastErrorCode print "Maximum Component Length: ", objItem.MaximumComponentLength print "Media Type: ", objItem.MediaType print "Name: ", objItem.Name print "Number Of Blocks: ", objItem.NumberOfBlocks print "PNP Device ID: ", objItem.PNPDeviceID z = objItem.PowerManagementCapabilities if z is None: a = 1 else: for x in z: print "Power Management Capabilities: ", x print "Power Management Supported: ", objItem.PowerManagementSupported print "Provider Name: ", objItem.ProviderName print "Purpose: ", objItem.Purpose print "Quotas Disabled: ", objItem.QuotasDisabled print "Quotas Incomplete: ", objItem.QuotasIncomplete print "Quotas Rebuilding: ", objItem.QuotasRebuilding print "Size: ", objItem.Size print "Status: ", objItem.Status print "Status Info: ", objItem.StatusInfo print "Supports Disk Quotas: ", objItem.SupportsDiskQuotas print "Supports File-Based Compression: ", objItem.SupportsFileBasedCompression print "System Creation Class Name: ", objItem.SystemCreationClassName print "System Name: ", objItem.SystemName print "Volume Dirty: ", objItem.VolumeDirty print "Volume Name: ", objItem.VolumeName print "Volume Serial Number: ", objItem.VolumeSerialNumber 

Encontré esta solución en Google, ligeramente modificada del original. Parecen bastante pythonicos y no necesitan importaciones “exóticas”

 import os, string available_drives = ['%s:' % d for d in string.ascii_uppercase if os.path.exists('%s:' % d)] 

Escribí este pedazo de código:

 import os drives = [ chr(x) + ":" for x in range(65,90) if os.path.exists(chr(x) + ":") ] 

Se basa en la respuesta de @Barmaley, pero tiene la ventaja de no usar el módulo de string , en caso de que no quiera usarlo. También funciona en mi sistema, a diferencia de la respuesta de @ SingleNegationElimination.

Solución más óptima basada en @RichieHindle

 def get_drives(): drives = [] bitmask = windll.kernel32.GetLogicalDrives() letter = ord('A') while bitmask > 0: if bitmask & 1: drives.append(chr(letter) + ':\\') bitmask >>= 1 letter += 1 return drives 

En Windows puedes hacer un os.popen

 import os print os.popen("fsutil fsinfo drives").readlines() 

Aquí está mi enfoque de mayor rendimiento (probablemente podría ser mayor):

 >>> from string import ascii_uppercase >>> reverse_alphabet = ascii_uppercase[::-1] >>> from ctypes import windll # Windows only >>> GLD = windll.kernel32.GetLogicalDisk >>> drives = ['%s:/'%reverse_alphabet[i] for i,v in enumerate(bin(GLD())[2:]) if v=='1'] 

Nadie realmente usa la funcionalidad performativa de Python …

Sí, no estoy siguiendo las convenciones de ruta estándar de Windows (‘\\’) …
En todos mis años de uso de python, no he tenido problemas con ‘/’ en ningún lugar de las rutas, y lo he hecho estándar en mis progtwigs.

Esta es otra gran solución si desea enumerar solo las unidades en su disco y las unidades de red no asignadas. Si quieres filtrar por diferentes atributos simplemente imprime drps.

 import psutil drps = psutil.disk_partitions() drives = [dp.device for dp in drps if dp.fstype == 'NTFS'] 

Como no tengo win32api instalado en mi campo de notebooks, utilicé esta solución usando wmic:

 import subprocess import string #define alphabet alphabet = [] for i in string.ascii_uppercase: alphabet.append(i + ':') #get letters that are mounted somewhere mounted_letters = subprocess.Popen("wmic logicaldisk get name", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) #erase mounted letters from alphabet in nested loop for line in mounted_letters.stdout.readlines(): if "Name" in line: continue for letter in alphabet: if letter in line: print 'Deleting letter %s from free alphabet %s' % letter alphabet.pop(alphabet.index(letter)) print alphabet 

alternativamente, puede obtener la diferencia de ambas listas como esta solución más simple (después de iniciar el subproceso wmic como montados en los boletines):

 #get output to list mounted_letters_list = [] for line in mounted_letters.stdout.readlines(): if "Name" in line: continue mounted_letters_list.append(line.strip()) rest = list(set(alphabet) - set(mounted_letters_list)) rest.sort() print rest 

Ambas soluciones son igualmente rápidas, pero supongo que establecer la lista es mejor por alguna razón, ¿no?

Como parte de una tarea similar, también necesitaba agarrar una letra de unidad libre. Decidí que quería la carta más alta disponible. Primero lo escribí de forma más idiomática, luego lo trituré en una línea para ver si aún tenía sentido. Tan asombrosos como las listas de comprensión son los conjuntos que amo para esto: unused=set(alphabet)-set(used) lugar de tener que hacer unused = [a for a in aphabet if a not in used] . ¡Cosas interesantes!

 def get_used_drive_letters(): drives = win32api.GetLogicalDriveStrings() drives = drives.split('\000')[:-1] letters = [d[0] for d in drives] return letters def get_unused_drive_letters(): alphabet = map(chr, range(ord('A'), ord('Z')+1)) used = get_used_drive_letters() unused = list(set(alphabet)-set(used)) return unused def get_highest_unused_drive_letter(): unused = get_unused_drive_letters() highest = list(reversed(sorted(unused)))[0] return highest 

El trazador de líneas:

 def get_drive(): highest = sorted(list(set(map(chr, range(ord('A'), ord('Z')+1))) - set(win32api.GetLogicalDriveStrings().split(':\\\000')[:-1])))[-1] 

También elegí el alfabeto usando map / range / ord / chr sobre el uso de string ya que las partes de string están en desuso.

si no quiere preocuparse por los problemas de plataformas cruzadas, incluidos los de plataformas Python como Pypy, y desea que se use algo decente de rendimiento cuando las unidades se actualicen durante el tiempo de ejecución:

 >>> from os.path import exists >>> from sys import platform >>> drives = ''.join( l for l in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' if exists('%s:/'%l) ) if platform=='win32' else '' >>> drives 'CZ' 

Aquí está mi prueba de rendimiento de este código:

 4000 iterations; threshold of min + 250ns: __________________________________________________________________________________________________________code___|_______min______|_______max______|_______avg______|_efficiency ⡇⠀⠀⢀⠀⠀⠀⠀⠀⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ ⣷⣷⣶⣼⣶⣴⣴⣤⣤⣧⣤⣤⣠⣠⣤⣤⣶⣤⣤⣄⣠⣦⣤⣠⣤⣤⣤⣤⣄⣠⣤⣠⣤⣤⣠⣤⣤⣤⣤⣤⣤⣄⣤⣤⣄⣤⣄⣤⣠⣀⣀⣤⣄⣤⢀⣀⢀⣠⣠⣀⣀⣤⣀⣠ drives = ''.join( l for l in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' if exists('%s:/'%l) ) if platform=='win32' else '' | 290.049ns | 1975.975ns | 349.911ns | 82.892%