2009-05-05 19 views

risposta

48
import win32api 

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

Adattato da: http://www.faqts.com/knowledge_base/view.phtml/aid/4670

+0

FANTASTICO. Ha funzionato perfetto –

+0

Ho appena provato in 2.6, e ho ottenuto una stringa vuota extra alla fine. Ancora una buona risposta. –

+0

@ Marco: edit per correggere – Claudiu

50

Senza utilizzando qualsiasi libreria esterna, se questo è importante per te:

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'] 
+0

Qual è il motivo di non usare string.lowercase o string.ascii_lowercase anziché string.letters [len (string.letters)/2:]? –

+0

@ John: Non c'è ragione - grazie per il suggerimento, ora cambiato in string.uppercase (perché per le lettere di unità preferisco tappi, non so perché 8-) – RichieHindle

+1

[c + ': \\' per C in string.lowercase se os.path.isdir (c + ': \\')] –

6

Questi sembrano risposte migliori. Ecco il mio hacker cruft

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

riffing un po 'sul risposta RichieHindle s'; non è davvero meglio, ma è possibile ottenere le finestre per fare il lavoro di venire con lettere effettivi dell'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:\\'] 
+1

Mi piace questa soluzione. Convenientemente non deve usare Win32APi. – WorldDominator

+0

Viene visualizzato questo errore quando si esegue il codice: –

+0

'UnicodeDecodeError: il codec 'charmap' non può decodificare il byte 0x81 nella posizione 586: caratteri mappa a ' –

8

Il Microsoft Script Repository include this recipe che potrebbe aiutare. Non ho una macchina Windows per testarlo, quindi non sono sicuro se vuoi "Name", "System Name", "Volume Name", o forse qualcos'altro.

+1

Grazie per il collegamento a Microsoft Script Repository. –

+0

Ho sempre pensato che sia una risorsa eccellente per i programmatori Windows che non è abbastanza conosciuta :-) –

+0

Un altro +1 per il collegamento al Microsoft Script Repository, non ne avevo mai sentito parlare prima. –

0

Come non ce l'ho installato sul mio Win32API campo dei notebook Ho usato questa soluzione utilizzando 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 

in alternativa si può ottenere la differenza sia da lista come questa soluzione più semplice (dopo il lancio sottoprocesso wmic come mounted_letters):

#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 

entrambe le soluzioni sono similiarly veloce, ma immagino all'elenco riportato è meglio per qualche motivo, no?

0

Come parte di un'attività simile, avevo anche bisogno di prendere una lettera di unità gratuita. Ho deciso che volevo la lettera più alta disponibile. L'ho scritto per la prima volta in modo più idiomatico, poi l'ho ritagliato su un 1-liner per vedere se aveva ancora senso. Per quanto impressionante come le list comprehensions, adoro set per questo: unused=set(alphabet)-set(used) invece di dover fare unused = [a for a in aphabet if a not in used]. Roba forte!

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 

L'uno di linea:

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

Ho anche scelto l'alfabeto usando la mappa/gamma/ord/chr oltre utilizzare stringa poiché parti di stringa sono obsoleti.

4

Abbiamo trovato questa soluzione su Google, leggermente modificata rispetto all'originale.Sembrano piuttosto pythonic e non ha bisogno di importazioni "esotici"

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

FWIW questo non è riuscito per me almeno una volta per un motivo sconosciuto – NirIzr

2

Ho scritto questo pezzo di codice:

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

Si basa su @ risposta di barmaley, ma ha il vantaggio di non utilizzare il string modulo, nel caso in cui non si voglia usarlo. Funziona anche sul mio sistema, a differenza della risposta di @ SingleNegationElimination.

1

soluzione più ottimale in base @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 
1

Ecco il mio approccio ad alte prestazioni (probabilmente potrebbe essere più elevato):

>>> 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'] 

nessuno usa davvero featurability performativa di pitone ...

Sì, non sto seguenti convenzioni percorso standard di Windows ('\\') ...
In tutti i miei anni di utilizzo di pitone, ho avuto nessun problema con i percorsi "/" utilizzati, e lo hanno reso standard nei miei programmi.

2

Su Windows si può fare un os.popen

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

Soluzione solo amministrativa sebbene – pstatix

Problemi correlati