如何用Python仅列出外部USB存储设备?(含USB硬盘、U盘等)
仅列出Windows下外部USB存储设备的Python实现(低依赖)
方法一:使用pywin32库(win32api 扩展)
如果已经安装了pywin32,可以结合win32api和WMI接口精准筛选USB设备,排除软盘等其他可移动存储:
import win32api import win32com.client def get_usb_drives(): usb_drives = [] # 获取所有逻辑驱动器,过滤掉末尾空字符串 drives = win32api.GetLogicalDriveStrings().split('\x00')[:-1] # 通过WMI查询USB磁盘设备 wmi = win32com.client.GetObject("winmgmts:") for disk in wmi.InstancesOf("Win32_DiskDrive"): # 仅筛选接口类型为USB的设备 if disk.InterfaceType == "USB": # 关联磁盘分区与逻辑驱动器 for partition in disk.Associators_("Win32_DiskDriveToDiskPartition"): for logical_disk in partition.Associators_("Win32_LogicalDiskToPartition"): drive_path = f"{logical_disk.DeviceID}\\" if drive_path in drives: usb_drives.append(drive_path) # 去重返回 return list(set(usb_drives)) print(get_usb_drives())
说明:该方法通过WMI直接关联USB磁盘设备与逻辑驱动器字母,准确性高,依赖pywin32库(通常通过pip install pywin32安装)。
方法二:使用ctypes(纯标准库,无额外依赖)
如果需要零第三方依赖,可使用Python标准库ctypes调用Windows原生API实现:
import ctypes from ctypes import wintypes # 加载Windows系统库 kernel32 = ctypes.WinDLL('kernel32', use_last_error=True) setupapi = ctypes.WinDLL('setupapi', use_last_error=True) cfgmgr32 = ctypes.WinDLL('cfgmgr32', use_last_error=True) # 定义常量与结构体 DRIVE_REMOVABLE = 2 GUID_DEVINTERFACE_DISK = '{53F56307-B6BF-11D0-94F2-00A0C91EFB8B}' DIGCF_PRESENT = 0x00000002 DIGCF_DEVICEINTERFACE = 0x00000010 class SP_DEVICE_INTERFACE_DATA(ctypes.Structure): _fields_ = [ ("cbSize", wintypes.DWORD), ("InterfaceClassGuid", wintypes.GUID), ("Flags", wintypes.DWORD), ("Reserved", wintypes.LPVOID) ] class SP_DEVINFO_DATA(ctypes.Structure): _fields_ = [ ("cbSize", wintypes.DWORD), ("ClassGuid", wintypes.GUID), ("DevInst", wintypes.DWORD), ("Reserved", wintypes.LPVOID) ] def get_usb_drives_ctypes(): usb_drives = [] # 获取所有逻辑驱动器 buf_size = kernel32.GetLogicalDriveStringsW(0, None) buf = ctypes.create_unicode_buffer(buf_size) kernel32.GetLogicalDriveStringsW(buf_size, buf) drives = [buf[i:i+4] for i in range(0, buf_size, 4) if buf[i]] # 枚举所有磁盘设备接口 disk_guid = wintypes.GUID(GUID_DEVINTERFACE_DISK) hdevinfo = setupapi.SetupDiGetClassDevsW(ctypes.byref(disk_guid), None, None, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE) if hdevinfo == wintypes.HANDLE(-1).value: return usb_drives interface_data = SP_DEVICE_INTERFACE_DATA() interface_data.cbSize = ctypes.sizeof(SP_DEVICE_INTERFACE_DATA) devinfo_data = SP_DEVINFO_DATA() devinfo_data.cbSize = ctypes.sizeof(SP_DEVINFO_DATA) index = 0 while setupapi.SetupDiEnumDeviceInterfaces(hdevinfo, None, ctypes.byref(disk_guid), index, ctypes.byref(interface_data)): index += 1 # 获取设备路径 req_size = wintypes.DWORD() setupapi.SetupDiGetDeviceInterfaceDetailW(hdevinfo, ctypes.byref(interface_data), None, 0, ctypes.byref(req_size), None) detail_buf = ctypes.create_string_buffer(req_size.value) if not setupapi.SetupDiGetDeviceInterfaceDetailW(hdevinfo, ctypes.byref(interface_data), detail_buf, req_size, None, ctypes.byref(devinfo_data)): continue # 判断设备是否为USB类型 dev_inst = devinfo_data.DevInst parent_devinst = wintypes.DWORD() if cfgmgr32.CM_Get_Parent(ctypes.byref(parent_devinst), dev_inst, 0) != 0: continue # 获取硬件ID验证USB标识 hw_id_buf = ctypes.create_unicode_buffer(256) cfgmgr32.CM_Get_Device_IDW(parent_devinst.value, hw_id_buf, ctypes.sizeof(hw_id_buf)//2, 0) if 'USB' not in hw_id_buf.value: continue # 映射到逻辑驱动器字母 device_path = ctypes.wstring_at(detail_buf) volume_buf = ctypes.create_unicode_buffer(1024) kernel32.GetVolumePathNamesForVolumeNameW(device_path, volume_buf, ctypes.sizeof(volume_buf)//2, None) if volume_buf.value: drive_letter = volume_buf.value.split('\\')[0] + '\\' if drive_letter in drives: usb_drives.append(drive_letter) setupapi.SetupDiDestroyDeviceInfoList(hdevinfo) return list(set(usb_drives)) print(get_usb_drives_ctypes())
说明:该方法完全基于Python标准库,直接调用Windows底层API,无需安装任何第三方包,适合对依赖严格的场景。
内容的提问来源于stack exchange,提问作者Basj
相关产品推荐
相关产品推荐

