有没有办法列出所有可用的 Windows 驱动器?
- 2025-02-27 09:06:00
- admin 原创
- 58
问题描述:
在 Python 中有没有办法列出 Windows 系统中所有当前正在使用的驱动器号?
(这次我的 Google 功力似乎让我失望了)
等效方法C++
:枚举 Windows 中所有可用的驱动器号
解决方案 1:
不使用任何外部库,如果这对你很重要:
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']
解决方案 2:
import win32api
drives = win32api.GetLogicalDriveStrings()
drives = drives.split(' ')[:-1]
print drives
摘自:
http: //www.faqts.com/knowledge_base/view.phtml/aid/4670
解决方案 3:
在 Google 上找到了这个解决方案,与原始解决方案略有修改。看起来非常符合 Python 风格,不需要任何“奇特”的导入
import os, string
available_drives = ['%s:' % d for d in string.ascii_uppercase if os.path.exists('%s:' % d)]
解决方案 4:
我写了这段代码:
import os
drives = [ chr(x) + ":" for x in range(65,91) if os.path.exists(chr(x) + ":") ]
它基于@Barmaley的答案,但优点是不使用string
模块,以防您不想使用它。与@SingleNegationElimination的答案不同,它也适用于我的系统。
解决方案 5:
这些看起来是更好的答案。以下是我的一些粗俗之谈
import os, re
re.findall(r"[A-Z]+:.*$",os.popen("mountvol /").read(),re.MULTILINE)
对RichieHindle的回答进行了一些改进;它并没有真正变得更好,但是你可以让 windows 来完成想出实际字母的工作
>>> 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' '))
[u'C:\\', u'D:\\']
解决方案 6:
Microsoft Script Repository包含此配方,可能会有所帮助。不过,我没有 Windows 机器来测试它,所以我不确定您是否想要“名称”、“系统名称”、“卷名称”或其他名称。
import win32com.client
strComputer = "."
objWMIService = win32com.client.Dispatch("WbemScripting.SWbemLocator")
objSWbemServices = objWMIService.ConnectServer(strComputer,"rootcimv2")
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
解决方案 7:
如果您只想列出磁盘上的驱动器而不是映射的网络驱动器,这是另一个很好的解决方案。如果您想按不同的属性进行过滤,只需打印 drps。
import psutil
drps = psutil.disk_partitions()
drives = [dp.device for dp in drps if dp.fstype == 'NTFS']
解决方案 8:
在 Windows 上你可以执行 os.popen
import os
print os.popen("fsutil fsinfo drives").readlines()
解决方案 9:
从python 3.12(2023 年 10 月 2 日发布)开始,您可以使用os.listdrives()
它将返回包含 Windows 系统上驱动器名称的列表。
该函数在底层GetLogicalDriveStringsW
使用了Windows API 。
>>> import os
>>> help(os.listdrives)
Help on built-in function listdrives in module nt:
listdrives()
Return a list containing the names of drives in the system.
A drive name typically looks like 'C:\\'.
>>> os.listdrives()
['C:\\']
解决方案 10:
基于@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
解决方案 11:
这是一个更简单的版本,无需安装任何附加模块或任何功能。由于驱动器字母不能超出 A 和 Z,因此您可以搜索每个字母是否有可用的路径,如下所示:
>>> import os
>>> for drive_letter in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
if os.path.exists(f'{drive_letter}:'):
print(f'{drive_letter}:')
else:
pass
单行:
>>> import os
>>> [f'{d}:' for d in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' if os.path.exists(f'{d}:')]
['C:', 'D:']
解决方案 12:
作为类似任务的一部分,我还需要获取一个空闲的驱动器号。我决定要获取可用的最高字母。我首先以更惯用的方式将其写出来,然后将其压缩为一行,看看是否仍然有意义。列表推导很棒,但我喜欢使用集合来实现这一点: unused=set(alphabet)-set(used)
而不必执行unused = [a for a in aphabet if a not in used]
。很酷的东西!
def get_used_drive_letters():
drives = win32api.GetLogicalDriveStrings()
drives = drives.split(' ')[:-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
一行代码:
def get_drive():
highest = sorted(list(set(map(chr, range(ord('A'), ord('Z')+1))) -
set(win32api.GetLogicalDriveStrings().split(':\\ ')[:-1])))[-1]
我还选择使用 map/range/ord/chr 来表示字母表,而不是使用字符串,因为字符串的部分功能已被弃用。
解决方案 13:
这是我的更高性能方法(可能更高):
>>> 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']
没有人真正使用 python 的性能特性......
是的,我没有遵循 Windows 标准路径约定('\\')...
在我使用 Python 的这些年里,在任何使用路径的地方我都没有遇到过'/'的问题,并且已经在我的程序中将它作为标准。
解决方案 14:
此代码将返回驱动器名称和字母的列表,例如:
['网关(C:)', 'EOS_DIGITAL(L:)', '音乐档案(O:)']
它仅使用标准库。它基于我在上面找到的一些想法。如果磁盘驱动器为空,例如没有磁盘的 CD-ROM,windll.kernel32.GetVolumeInformationW() 将返回 0。此代码未列出这些空驱动器。
这两行捕获了所有驱动器的字母:
bitmask = (bin(windll.kernel32.GetLogicalDrives())[2:])[::-1] # strip off leading 0b and reverse
drive_letters = [ascii_uppercase[i] + ':/' for i, v in enumerate(bitmask) if v == '1']
以下是完整流程:
from ctypes import windll, create_unicode_buffer, c_wchar_p, sizeof
from string import ascii_uppercase
def get_win_drive_names():
volumeNameBuffer = create_unicode_buffer(1024)
fileSystemNameBuffer = create_unicode_buffer(1024)
serial_number = None
max_component_length = None
file_system_flags = None
drive_names = []
# Get the drive letters, then use the letters to get the drive names
bitmask = (bin(windll.kernel32.GetLogicalDrives())[2:])[::-1] # strip off leading 0b and reverse
drive_letters = [ascii_uppercase[i] + ':/' for i, v in enumerate(bitmask) if v == '1']
for d in drive_letters:
rc = windll.kernel32.GetVolumeInformationW(c_wchar_p(d), volumeNameBuffer, sizeof(volumeNameBuffer),
serial_number, max_component_length, file_system_flags,
fileSystemNameBuffer, sizeof(fileSystemNameBuffer))
if rc:
drive_names.append(f'{volumeNameBuffer.value}({d[:2]})') # disk_name(C:)
return drive_names
解决方案 15:
这将有助于在 Windows 操作系统中找到有效的驱动器
import os
import string
drive = string.ascii_uppercase
valid_drives = []
for each_drive in drive:
if os.path.exist(each_drive+":\\\"):
print(each_drive)
valid_drives.append(each_drive+":\\\")
print(valid_drives)
输出将是
C
D
E
['C:\\','D:\\','E:\\']
解决方案 16:
如果您只想要每个驱动器的字母,您可以:
from win32.win32api import GetLogicalDriveStrings
drives = [drive for drive in GetLogicalDriveStrings()[0]]
解决方案 17:
由于我的笔记本电脑上没有安装 win32api,因此我使用 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
或者,您可以从两个列表中获取差异,就像这个更简单的解决方案一样(在将 wmic 子进程启动为 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
两种解决方案都同样快,但我猜出于某种原因设置列表会更好,对吗?
解决方案 18:
如果您不想担心跨平台问题(包括跨 Python 平台(如 Pypy)的问题),并且希望在运行时更新驱动器时使用一些性能良好的东西:
>>> 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'
以下是我对该代码的性能测试:
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%
解决方案 19:
使用 Python 中的命令提示符窗口列出硬盘驱动器
类似地,你可以在 Linux 上进行一些修改
import os,re
regex = r"([^s]*:)"
driver = os.popen("wmic logicaldisk get name").read()
print(re.findall(regex, driver))
示例输出:
['A:', 'C:', 'D:', 'E:', 'F:', 'G:', 'H:', 'I:', 'J:', 'L:']
解决方案 20:
在 Python 3.12 中,现在有一个 listdrives 函数。
在 Windows 上添加 os.listdrives()、os.listvolumes() 和 os.listmounts() 函数,用于枚举驱动器、卷和挂载点。(由 Steve Dower 在 gh-102519 中贡献。)
扫码咨询,免费领取项目管理大礼包!