在 Python 中读取硬盘的所有信息是一个复杂的任务,因为它涉及到操作系统底层接口、硬件抽象和管理员权限。没有一个单一的库可以跨平台地获取所有信息。
![图片[1]_Python读取硬盘所有信息的完整方法_知途无界](https://zhituwujie.com/wp-content/uploads/2026/01/d2b5ca33bd20260129102439.png)
下面我将为您提供一个分层次、跨平台的完整方法,涵盖从基础的文件系统信息到深入的磁盘硬件信息。
核心思路
- 分层获取:先获取高级的逻辑分区信息(如 Windows 的 C: 盘,Linux 的 /dev/sda1),再深入到物理磁盘信息(如 /dev/sda),最后尝试获取最底层的 SMART 健康数据。
- 跨平台工具:
- Windows: 主要依赖
wmi和pywin32库来调用 WMI (Windows Management Instrumentation)。 - Linux: 主要依赖解析
/sys/class/block,/proc/mounts和调用系统命令(如lsblk,fdisk,smartctl)。 - macOS: 主要依赖
subprocess模块调用系统命令(如diskutil)。
- Windows: 主要依赖
准备工作:安装必要的库
首先,您需要安装一些第三方库。
# 跨平台的 WMI 访问(主要用于 Windows)
pip install wmi
# 如果需要更深入的 Windows API 访问
pip install pywin32
# 用于执行系统命令(Linux/macOS 必需)
# 标准库,无需安装
# 注意:要获取 SMART 信息,必须在系统上安装 smartmontools
# Linux (Debian/Ubuntu): sudo apt-get install smartmontools
# macOS: brew install smartmontools
# Windows: 下载并安装 smartmontools for Windows
完整代码实现
以下脚本提供了一个尽可能完整的示例,您可以根据目标平台运行相应的部分。
import os
import sys
import platform
import subprocess
import json
from collections import defaultdict
# ==================== Windows 特定功能 ====================
def get_windows_drive_info():
"""使用 WMI 获取 Windows 驱动器信息"""
try:
import wmi
c = wmi.WMI()
drive_info = []
# 获取逻辑磁盘(分区)信息
for disk in c.Win32_LogicalDisk():
info = {
"DeviceID": disk.DeviceID, # e.g., "C:"
"DriveType": {2: "Removable", 3: "Local Disk", 5: "CD-ROM"}.get(disk.DriveType, "Unknown"),
"FileSystem": disk.FileSystem,
"FreeSpaceGB": round(int(disk.FreeSpace) / (1024**3), 2),
"SizeGB": round(int(disk.Size) / (1024**3), 2) if disk.Size else 0,
"VolumeName": disk.VolumeName,
}
drive_info.append(info)
# 获取物理磁盘信息
physical_disks = []
for disk in c.Win32_DiskDrive():
# 关联分区
partitions = []
for partition in disk.associators("Win32_DiskDriveToDiskPartition"):
logical_disks = [ld.DeviceID for ld in partition.associators("Win32_LogicalDiskToPartition")]
partitions.append({
"Name": partition.Name,
"Description": partition.Description,
"LogicalDisks": logical_disks
})
disk_data = {
"Model": disk.Model,
"InterfaceType": disk.InterfaceType,
"MediaType": disk.MediaType,
"SerialNumber": disk.SerialNumber.strip() if disk.SerialNumber else "N/A",
"SizeGB": round(int(disk.Size) / (1024**3), 2) if disk.Size else 0,
"Partitions": partitions
}
physical_disks.append(disk_data)
return {"logical_drives": drive_info, "physical_disks": physical_disks}
except ImportError:
print("请安装 wmi 库: pip install wmi")
return None
except Exception as e:
print(f"WMI 查询失败: {e}")
return None
def get_smart_info_windows(device_id):
"""
在 Windows 上使用 smartctl 获取 SMART 信息
device_id 格式如 "\\\\.\\PhysicalDrive0"
"""
try:
# 注意:需要管理员权限运行 Python
cmd = f'smartctl -a "{device_id}"'
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, check=True)
# 简单解析输出,实际应用中可能需要更复杂的解析
return result.stdout
except subprocess.CalledProcessError as e:
return f"无法获取 SMART 信息: {e.stderr}"
except FileNotFoundError:
return "未找到 smartctl,请确保已安装 smartmontools 并将其添加到 PATH。"
# ==================== Linux 特定功能 ====================
def get_linux_drive_info():
"""在 Linux 上通过解析文件和命令获取驱动器信息"""
drive_info = {"logical_mounts": [], "physical_disks": []}
# 1. 获取挂载点信息 (/proc/mounts)
try:
with open('/proc/mounts', 'r') as f:
for line in f:
parts = line.split()
if parts[0].startswith('/dev/'):
device, mount_point, fs_type = parts[0], parts[1], parts[2]
# 避免重复添加
if not any(m['MountPoint'] == mount_point for m in drive_info["logical_mounts"]):
# 尝试获取磁盘空间信息
statvfs = os.statvfs(mount_point)
free_gb = round(statvfs.f_frsize * statvfs.f_bavail / (1024**3), 2)
total_gb = round(statvfs.f_frsize * statvfs.f_blocks / (1024**3), 2)
drive_info["logical_mounts"].append({
"Device": device,
"MountPoint": mount_point,
"FileSystem": fs_type,
"FreeSpaceGB": free_gb,
"TotalSizeGB": total_gb
})
except Exception as e:
print(f"读取 /proc/mounts 失败: {e}")
# 2. 获取物理磁盘信息 (/sys/class/block 和 lsblk)
try:
# 列出所有块设备
block_devices = [d for d in os.listdir('/sys/class/block') if d.startswith(('sd', 'hd', 'nvme'))]
# 使用 lsblk 获取更友好的树状结构
lsblk_result = subprocess.run(['lsblk', '-o', 'NAME,SIZE,TYPE,MOUNTPOINT,MODEL'], capture_output=True, text=True)
print("--- lsblk 输出 ---")
print(lsblk_result.stdout)
# 手动解析 /sys 来获取型号和序列号(更复杂)
for dev in block_devices:
dev_path = f"/sys/class/block/{dev}"
model_path = os.path.join(dev_path, "device/model")
vendor_path = os.path.join(dev_path, "device/vendor")
model = "N/A"
if os.path.exists(model_path):
with open(model_path, 'r') as f:
model = f.read().strip()
size_path = os.path.join(dev_path, "size")
size_sectors = 0
if os.path.exists(size_path):
with open(size_path, 'r') as f:
size_sectors = int(f.read().strip())
# 扇区大小通常为512字节
size_gb = round((size_sectors * 512) / (1024**3), 2)
drive_info["physical_disks"].append({
"Name": dev, # e.g., sda
"Model": model,
"SizeGB": size_gb,
"FullPath": f"/dev/{dev}"
})
except Exception as e:
print(f"解析 Linux 磁盘信息失败: {e}")
return drive_info
def get_smart_info_linux(device_path):
"""
在 Linux 上使用 smartctl 获取 SMART 信息
device_path 格式如 "/dev/sda"
"""
try:
# 注意:需要 root 权限运行
cmd = f'sudo smartctl -a "{device_path}"'
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, check=True)
return result.stdout
except subprocess.CalledProcessError as e:
return f"无法获取 SMART 信息 (可能需要 sudo): {e.stderr}"
except FileNotFoundError:
return "未找到 smartctl,请确保已安装 smartmontools。"
# ==================== macOS 特定功能 ====================
def get_macos_drive_info():
"""在 macOS 上使用 diskutil 获取驱动器信息"""
drive_info = {"logical_volumes": [], "physical_disks": []}
try:
# 获取卷信息
result = subprocess.run(['diskutil', 'list', '-plist'], capture_output=True, text=True)
# plist 解析比较复杂,这里用非 plist 方式演示
result_json = subprocess.run(['diskutil', 'list', '-json'], capture_output=True, text=True, check=True)
data = json.loads(result_json.stdout)
# 解析 JSON 输出 (简化版)
for disk in data.get('AllDisksAndPartitions', []):
disk_info = {
"DeviceIdentifier": disk['DeviceIdentifier'], # e.g., disk0
"Size": disk['Size'],
"Partitions": []
}
for part in disk.get('Partitions', []):
part_info = {
"DeviceIdentifier": part['DeviceIdentifier'], # e.g., disk0s1
"MountPoint": part.get('MountPoint'),
"Size": part['Size']
}
disk_info["Partitions"].append(part_info)
if part.get('MountPoint'):
# 获取文件系统信息
fs_result = subprocess.run(['df', '-h', part['MountPoint']], capture_output=True, text=True)
drive_info["logical_volumes"].append({
"Device": part['DeviceIdentifier'],
"MountPoint": part['MountPoint'],
"FilesystemInfo": fs_result.stdout.splitlines()[1] if len(fs_result.stdout.splitlines()) > 1 else "N/A"
})
drive_info["physical_disks"].append(disk_info)
print(json.dumps(data, indent=2)) # 打印原始 JSON 供参考
except subprocess.CalledProcessError as e:
print(f"diskutil 命令失败: {e}")
except json.JSONDecodeError:
print("解析 diskutil JSON 输出失败。")
except Exception as e:
print(f"获取 macOS 磁盘信息时发生未知错误: {e}")
return drive_info
def get_smart_info_macos(device_path):
"""
在 macOS 上使用 smartctl 获取 SMART 信息
device_path 格式如 "/dev/disk0"
"""
# 在 macOS 上,设备名通常是 /dev/diskX,但 smartctl 可能需要 /dev/rdiskX
# 这里直接使用传入的路径
try:
cmd = f'smartctl -a "{device_path}"'
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, check=True)
return result.stdout
except subprocess.CalledProcessError as e:
return f"无法获取 SMART 信息: {e.stderr}"
except FileNotFoundError:
return "未找到 smartctl,请确保已安装 smartmontools。"
# ==================== 主函数 ====================
def main():
system = platform.system()
print(f"正在检测 {system} 系统的硬盘信息...\n")
all_disk_data = {}
if system == "Windows":
all_disk_data = get_windows_drive_info()
if all_disk_data and all_disk_data.get("physical_disks"):
print("\n--- 物理磁盘 SMART 信息 (示例: 第一块磁盘) ---")
first_disk = all_disk_data["physical_disks"][0]
device_id = f"\\\\.\\{first_disk['Model'].replace(' ', '_')}" # 构造一个可能的 ID,实际可能需要调整
# 更可靠的方法是使用 Win32_DiskDrive 的 Index 属性构造 "\\\\.\\PhysicalDrive0"
# 这里我们简化演示,实际需要映射关系
print("注意:Windows SMART 查询需要精确的设备标识符,且需管理员权限。")
# print(get_smart_info_windows("\\\\.\\PhysicalDrive0"))
elif system == "Linux":
all_disk_data = get_linux_drive_info()
if all_disk_data and all_disk_data.get("physical_disks"):
print("\n--- 物理磁盘 SMART 信息 (示例: 第一块磁盘) ---")
first_disk = all_disk_data["physical_disks"][0]
print(get_smart_info_linux(first_disk['FullPath']))
elif system == "Darwin": # macOS
all_disk_data = get_macos_drive_info()
# macOS 的 diskutil 输出已经很丰富,SMART 信息通常也包含在内
print("\n--- macOS 磁盘信息已通过 diskutil 获取 ---")
else:
print(f"不支持的操作系统: {system}")
# 打印收集到的信息摘要
print("\n\n========== 收集到的信息摘要 ==========")
print(json.dumps(all_disk_data, indent=2, ensure_ascii=False))
if __name__ == "__main__":
# 检查管理员/root权限
if os.name == 'nt': # Windows
import ctypes
if not ctypes.windll.shell32.IsUserAnAdmin():
print("警告:建议以管理员身份运行以获取完整的 SMART 信息。")
else: # Linux/macOS
if os.geteuid() != 0:
print("警告:建议以 root 权限运行(sudo)以获取完整的 SMART 信息和所有磁盘详情。")
main()
关键注意事项和局限性
- 权限!权限!权限!
- Windows: 读取 SMART 信息和某些详细的磁盘属性需要以管理员身份运行 Python 脚本。
- Linux/macOS: 读取
/sys/class/block下的某些文件和执行smartctl通常需要 root 权限(使用sudo)。
- SMART 工具的依赖性: 获取硬盘健康状态的核心是
smartmontools。必须在系统上预先安装它,并且 Python 脚本能够找到它(PATH环境变量)。 - 跨平台差异:
- Windows 的 WMI 非常强大,能提供结构化的信息,但仅限于 Windows。
- Linux 的信息分散在
/proc、/sys和各种命令行工具中,需要组合和解析。 - macOS 的
diskutil是首选工具,但其输出格式(尤其是 plist/json)可能随版本变化。
- 信息解析的复杂性: 上述代码中的 SMART 信息解析非常简单(直接返回文本)。在实际应用中,您需要使用正则表达式或专门的解析库(如
pysmart)来提取温度、通电时间、坏道计数等关键属性。 - 设备名称映射: 在 Windows 上,将逻辑驱动器(C:)映射到物理磁盘(
\\.\PhysicalDrive0)需要知道磁盘分区布局,这在代码中处理起来比较复杂。上面的示例只是演示了基本方法。
总结
这个完整的方案为您提供了一个坚实的基础。您可以根据具体需求,针对您的目标平台,深入开发和优化其中的某个部分。例如,您可以专注于完善 Linux 下的 SMART 信息解析,或者为 Windows 开发一个更健壮的逻辑-物理磁盘映射器。
© 版权声明
文中内容均来源于公开资料,受限于信息的时效性和复杂性,可能存在误差或遗漏。我们已尽力确保内容的准确性,但对于因信息变更或错误导致的任何后果,本站不承担任何责任。如需引用本文内容,请注明出处并尊重原作者的版权。
THE END

























暂无评论内容