web-dev-qa-db-fra.com

Existe-t-il un moyen de répertorier toutes les lettres de lecteur disponibles en python?

Plus ou moins ce qui est écrit sur le panneau: existe-t-il un moyen (simple) de lister toutes les lettres de lecteur actuellement utilisées dans un système Windows?

(Mon google-fu semble m'avoir laissé tomber sur celui-ci.)

En relation:

37
Electrons_Ahoy
import win32api

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

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

54
Ayman Hourieh

Sans utiliser de bibliothèques externes, si cela vous tient à cœur:

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 __== '__main__':
    print get_drives()     # On my PC, this prints ['A', 'C', 'D', 'F', 'H']
56
RichieHindle

Celles-ci ressemblent à de meilleures réponses. Voici mon crétin hack

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

Riffing un peu sur RichieHindle réponse de /; ce n'est pas vraiment mieux, mais vous pouvez avoir Windows pour faire le travail de trouver de vraies lettres 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:\\']

Le Microsoft Script Repository inclut cette recette qui pourrait vous aider. Cependant, je n'ai pas de machine Windows pour le tester, donc je ne suis pas sûr de vouloir "Nom", "Nom du système", "Nom du volume" ou peut-être autre chose.

8
John Fouhy

Trouvé cette solution sur Google, légèrement modifiée par rapport à l'original. Semble jolie Pythonic et n'a pas besoin d'importations "exotiques"

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

Solution plus optimale 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
3
tiredgin

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 la réponse de @ Barmaley, mais présente l'avantage de ne pas utiliser le module string Au cas où vous ne voudriez pas l'utiliser. Cela fonctionne également sur mon système, contrairement à la réponse de @ SingleNegationElimination.

3
Sebastian Hietsch

Sous Windows, vous pouvez faire un os.popen

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

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

>>> 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 la fonctionnalité performative de python ...

Oui, je ne suis pas les conventions de chemin standard Windows ('\\') ... 
Au cours de toutes mes années d’utilisation de python, je n’ai rencontré aucun problème avec "/" où que des chemins soient utilisés et l’ai standardisé dans mes programmes.

1
Tcll

Voici une autre excellente solution si vous souhaitez répertorier uniquement les lecteurs de votre disque et non les lecteurs réseau mappés. Si vous voulez filtrer par différents attributs, imprimez simplement les drps.

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

Dans le cadre d'une tâche similaire, j'avais également besoin d'une lettre de lecteur gratuite. J'ai décidé que je voulais la plus haute lettre disponible. Je l’écrivis d’abord de façon plus idiomatique, puis je l’écrivis sur une ligne pour voir si cela avait encore un sens. Aussi géniaux que soient les compréhensions de liste, j'adore les ensembles pour ceci: unused=set(alphabet)-set(used) au lieu de devoir 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 doublure:

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 map/range/ord/chr sur en utilisant string car certaines parties de string sont déconseillées.

0
flutefreak7

Comme je n’ai pas installé win32api sur mon parc de cahiers, j’utilisais cette solution avec 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

alternativement, vous pouvez obtenir la différence entre les deux listes de la manière suivante:

#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 similaires rapidement, mais je suppose que la liste est mieux pour une raison quelconque, non?

0
Pulec

si vous ne souhaitez pas vous soucier des problèmes multi-plateformes, y compris ceux des plates-formes python telles que Pypy, et que vous souhaitiez utiliser un outil assez performant lorsque les lecteurs sont mis à jour pendant l'exécution:

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

voici mon test de performance de ce code:

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%
0
Tcll