如何使用Python判断Windows系统安装在SSD还是HDD上
Python检测Windows系统盘是SSD还是HDD实现方案
核心判断逻辑分两步:
- 定位Windows系统实际安装所在的物理磁盘,避免和其他挂载的数据盘混淆
- 读取目标物理磁盘的介质属性,区分SSD和HDD
Windows系统从Vista版本开始提供了原生的磁盘属性查询接口,最通用的判断依据是*磁盘寻道惩罚(Seek Penalty)*属性:HDD机械盘存在机械寻道开销,该属性值为True;SSD固态盘无机械寻道过程,该属性值为False。Win8及以上版本还可以直接读取磁盘的MediaType字段直接拿到介质类型,结果更直观。
方法1:无第三方依赖实现(推荐)
纯用Python标准库ctypes调用Windows原生API完成检测,不需要安装任何第三方包,普通用户权限即可运行:
import ctypes from ctypes import wintypes import os # 定义Windows API所需的结构体和常量 IOCTL_STORAGE_QUERY_PROPERTY = 0x2D1400 StorageDeviceSeekPenaltyProperty = 7 class STORAGE_PROPERTY_QUERY(ctypes.Structure): _fields_ = [ ("PropertyId", wintypes.DWORD), ("QueryType", wintypes.DWORD), ("AdditionalParameters", ctypes.c_byte * 1) ] class DEVICE_SEEK_PENALTY_DESCRIPTOR(ctypes.Structure): _fields_ = [ ("Version", wintypes.DWORD), ("Size", wintypes.DWORD), ("IncursSeekPenalty", wintypes.BOOLEAN) ] def get_system_drive_number(): """获取系统所在物理磁盘的编号""" system_root = os.environ.get("SystemRoot", "C:\\Windows") system_drive = os.path.splitdrive(system_root)[0].rstrip(":") volume_path = f"\\\\.\\{system_drive}:" GENERIC_READ = 0x80000000 FILE_SHARE_READ = 0x1 FILE_SHARE_WRITE = 0x2 OPEN_EXISTING = 3 handle = ctypes.windll.kernel32.CreateFileW( volume_path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, None, OPEN_EXISTING, 0, None ) if handle == wintypes.HANDLE(-1).value: raise ctypes.WinError() # 查询卷对应的物理磁盘号 IOCTL_STORAGE_GET_DEVICE_NUMBER = 0x2D1080 class STORAGE_DEVICE_NUMBER(ctypes.Structure): _fields_ = [("DeviceType", wintypes.DWORD), ("DeviceNumber", wintypes.DWORD), ("PartitionNumber", wintypes.DWORD)] sdn = STORAGE_DEVICE_NUMBER() bytes_returned = wintypes.DWORD() ret = ctypes.windll.kernel32.DeviceIoControl( handle, IOCTL_STORAGE_GET_DEVICE_NUMBER, None, 0, ctypes.byref(sdn), ctypes.sizeof(sdn), ctypes.byref(bytes_returned), None ) ctypes.windll.kernel32.CloseHandle(handle) if not ret: raise ctypes.WinError() return sdn.DeviceNumber def is_system_drive_ssd(): """判断系统盘是否为SSD""" disk_num = get_system_drive_number() disk_path = f"\\\\.\\PhysicalDrive{disk_num}" GENERIC_READ = 0x80000000 FILE_SHARE_READ = 0x1 FILE_SHARE_WRITE = 0x2 OPEN_EXISTING = 3 handle = ctypes.windll.kernel32.CreateFileW( disk_path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, None, OPEN_EXISTING, 0, None ) if handle == wintypes.HANDLE(-1).value: raise ctypes.WinError() # 查询寻道惩罚属性 query = STORAGE_PROPERTY_QUERY() query.PropertyId = StorageDeviceSeekPenaltyProperty query.QueryType = 0 descriptor = DEVICE_SEEK_PENALTY_DESCRIPTOR() bytes_returned = wintypes.DWORD() ret = ctypes.windll.kernel32.DeviceIoControl( handle, IOCTL_STORAGE_QUERY_PROPERTY, ctypes.byref(query), ctypes.sizeof(query), ctypes.byref(descriptor), ctypes.sizeof(descriptor), ctypes.byref(bytes_returned), None ) ctypes.windll.kernel32.CloseHandle(handle) if not ret: raise ctypes.WinError() # 有寻道惩罚是HDD,没有就是SSD return not descriptor.IncursSeekPenalty if __name__ == "__main__": if is_system_drive_ssd(): print("当前系统安装在SSD上") else: print("当前系统安装在HDD上")
方法2:使用WMI模块实现(代码更简洁)
如果允许安装第三方依赖,可以用wmi模块简化代码,先执行安装命令:pip install wmi
对应实现代码:
import wmi import os def is_system_drive_ssd(): c = wmi.WMI() # 获取系统盘盘符 system_drive = os.path.splitdrive(os.environ.get("SystemRoot", "C:\\Windows"))[0] # 找到系统盘关联的物理磁盘 for partition in c.Win32_DiskPartition(): for logical_disk in partition.associators("Win32_LogicalDiskToPartition"): if logical_disk.DeviceID == system_drive: physical_disk = c.Win32_DiskDrive(DeviceID=partition.DiskDrive)[0] # 优先判断MediaType,没有的话用寻道惩罚属性判断 if hasattr(physical_disk, "MediaType") and "SSD" in str(physical_disk.MediaType): return True return not bool(physical_disk.SeekPenalty) return False if __name__ == "__main__": print("系统安装在SSD上" if is_system_drive_ssd() else "系统安装在HDD上")
注意事项
- 以上方案在Win7/Win10/Win11系统下测试可用,Windows XP及更老版本因系统API不支持无法使用
- 逻辑会自动定位系统所在物理磁盘,不会误判其他挂载的数据盘类型
- 对SATA SSD、NVMe SSD、机械HDD均可准确识别,不会出现类型混淆
- 如果系统盘部署在硬件RAID阵列上,部分RAID卡不会透传单块磁盘的介质属性,可能导致判断失效,这类场景需要对接对应RAID卡的管理接口获取磁盘信息。
内容的提问来源于stack exchange,提问作者Temal
相关产品推荐
相关产品推荐

