2009-05-05 9 views

Répondre

48
import win32api 

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

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

+0

FANTASTIQUE. Travaillé parfait. –

+0

Je l'ai juste essayé en 2.6, et j'ai obtenu une chaîne vide supplémentaire à la fin. Toujours une bonne réponse. –

+0

@Mark: modifier pour corriger – Claudiu

50

Sans en utilisant des bibliothèques externes, si cela vous intéresse:

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

N'importe quelle raison de ne pas utiliser string.lowercase ou string.ascii_lowercase au lieu de string.letters [len (string.letters)/2:]? –

+0

@John: Aucune raison - merci pour la suggestion, maintenant changé en string.uppercase (parce que pour les lettres de lecteur je préfère les caps, je ne sais pas pourquoi 8-) – RichieHindle

+1

[c + ': \\' pour c dans string.lowercase si os.path.isdir (c + ': \\')] –

6

Elles ressemblent à de meilleures réponses. Voici mon hackish cruft

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

Riffing un peu sur la réponse de RichieHindle; ce n'est pas vraiment mieux, mais vous pouvez obtenir des fenêtres pour faire le travail de venir avec des lettres réelles de l'alphabet

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

J'aime cette solution. Pratiquement n'a pas à utiliser le win32api. – WorldDominator

+0

Je reçois cette erreur lors de l'exécution de votre code: –

+0

'UnicodeDecodeError: codec 'charmap' ne peut pas décoder octet 0x81 en position 586: le caractère correspond à ' –

8

Le Microsoft Script Repository comprend this recipe qui pourrait aider. Je n'ai pas de machine Windows pour le tester, donc je ne sais pas si vous voulez "Nom", "Nom du système", "Nom du volume", ou peut-être autre chose.

+1

Merci pour le lien vers Microsoft Script Repository. –

+0

J'ai toujours pensé que c'est une excellente ressource pour les progarmers Windows qui n'est pas assez connue :-) –

+0

Un autre +1 pour le lien vers le Microsoft Script Repository, je n'en avais jamais entendu parler auparavant. –

0

Comme je ne l'ai installé sur mon win32api domaine des ordinateurs portables j'ai utilisé cette solution à l'aide 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 

Sinon, vous pouvez obtenir la différence à la fois cette liste comme solution plus simple (après le lancement de sous-processus wmic comme mount_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 

les deux solutions sont tout aussi rapides, mais je suppose que la liste est meilleure pour une raison quelconque, non?

0

Dans le cadre d'une tâche similaire, j'ai également eu besoin de saisir une lettre de lecteur libre. J'ai décidé que je voulais la plus haute lettre disponible. Je l'ai d'abord écrit plus idiomatiquement, puis je l'ai croisé en 1 pour voir si cela avait encore du sens. Aussi génial que la liste des compréhensions sont j'aime jeux pour ceci: unused=set(alphabet)-set(used) au lieu d'avoir à faire unused = [a for a in aphabet if a not in used]. Truc cool!

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 

La seule ligne:

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

J'ai aussi choisi l'alphabet en utilisant la carte/plage/ord/chr sur l'aide de ficelle depuis les parties de la chaîne sont déconseillés.

4

J'ai trouvé cette solution sur Google, légèrement modifiée par rapport à l'original.Semblent assez pythonique et n'a pas besoin de « exotiques » importations

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

FWIW cela a échoué pour moi au moins une fois pour une raison inconnue – NirIzr

2

J'ai écrit ce morceau de code:

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

Il est basé sur @ réponse de Barmaley, mais a l'avantage de ne pas utiliser la string module, au cas où vous ne voudriez pas l'utiliser. Cela fonctionne également sur mon système, contrairement à la réponse de @ SingleNegationElimination.

1

Plus solution basée sur @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

Voici mon approche plus performante (pourrait probablement être plus élevé):

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

Personne n'utilise vraiment performative python featurability ...

Oui, je ne suis pas les conventions de chemin standard de Windows ('\\') ...
Dans toutes mes années d'utilisation de python, j'ai eu aucun problème avec '/' partout où les chemins sont utilisés, et l'ont rendu standard dans mes programmes.

2

Sous Windows, vous pouvez faire un

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

Admin seule solution si – pstatix

Questions connexes