如何在Windows10下无需调用Shell,用Python弹出外部驱动器?
在Windows 10下用Python实现备份后自动弹出外部驱动器
下面给你两种可行的实现方案,都是Windows原生支持的,不需要额外安装第三方库:
方法1:调用系统自带的diskpart命令(简单易上手)
Windows自带的diskpart工具可以安全卸载外部驱动器,我们可以用Python的subprocess模块调用它完成弹出操作。
代码示例
import subprocess def eject_drive(drive_letter): # 生成diskpart执行脚本,注意盘符要去掉冒号 diskpart_cmd = f"select volume {drive_letter[:-1]}\nremove all dismount\n" # 调用diskpart执行脚本 try: subprocess.run( ["diskpart", "/s", "-"], input=diskpart_cmd.encode("utf-8"), check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) print(f"驱动器 {drive_letter} 已成功弹出") except subprocess.CalledProcessError as e: print(f"弹出失败:{e.stderr.decode('utf-8')}") # 备份完成后调用,替换成你的外部驱动器盘符(比如"E:") eject_drive("E:")
注意事项
- 脚本需要以管理员权限运行,否则diskpart无法执行卸载操作
- 执行弹出前,务必确保所有备份文件已经完全写入驱动器,可以在文件复制完成后调用
os.sync()(或者用shutil.copy2替代普通复制,它会确保文件元数据也同步)
方法2:用ctypes调用Windows原生API(更稳定)
如果不想依赖外部命令,可以直接调用Windows的设备管理API来弹出驱动器,这种方式更底层,稳定性更好。
代码示例
import ctypes from ctypes import wintypes # 加载Windows API库 setupapi = ctypes.WinDLL("setupapi.dll") cfgmgr32 = ctypes.WinDLL("cfgmgr32.dll") # 定义API函数的参数和返回值类型 setupapi.SetupDiGetClassDevsW.argtypes = [wintypes.LPCGUID, wintypes.LPCWSTR, wintypes.HWND, wintypes.DWORD] setupapi.SetupDiGetClassDevsW.restype = wintypes.HDEVINFO setupapi.SetupDiEnumDeviceInfo.argtypes = [wintypes.HDEVINFO, wintypes.DWORD, wintypes.PSP_DEVINFO_DATA] setupapi.SetupDiEnumDeviceInfo.restype = wintypes.BOOL cfgmgr32.CM_Get_Device_IDW.argtypes = [wintypes.DWORD, wintypes.LPWSTR, wintypes.DWORD, wintypes.DWORD] cfgmgr32.CM_Get_Device_IDW.restype = wintypes.DWORD cfgmgr32.CM_Request_Device_EjectW.argtypes = [wintypes.HDEVINFO, wintypes.PSP_DEVINFO_DATA, wintypes.LPCWSTR, wintypes.DWORD, wintypes.DWORD] cfgmgr32.CM_Request_Device_EjectW.restype = wintypes.DWORD def eject_drive(device_instance_id): # 获取当前连接的USB存储设备列表 hdevinfo = setupapi.SetupDiGetClassDevsW(None, "USBSTOR", None, 0x00000001) # DIGCF_PRESENT if hdevinfo == wintypes.HDEVINFO(-1).value: raise ctypes.WinError() devinfo_data = wintypes.SP_DEVINFO_DATA() devinfo_data.cbSize = ctypes.sizeof(devinfo_data) index = 0 while setupapi.SetupDiEnumDeviceInfo(hdevinfo, index, ctypes.byref(devinfo_data)): index += 1 # 获取当前设备的实例ID buf = ctypes.create_unicode_buffer(1024) if cfgmgr32.CM_Get_Device_IDW(devinfo_data.DevInst, buf, ctypes.sizeof(buf)//2, 0) != 0: continue if buf.value == device_instance_id: # 执行弹出操作 result = cfgmgr32.CM_Request_Device_EjectW(hdevinfo, ctypes.byref(devinfo_data), None, 0, 0) if result != 0: raise ctypes.WinError(result) print("驱动器已成功弹出") break else: raise ValueError("未找到目标设备") setupapi.SetupDiDestroyDeviceInfoList(hdevinfo) # 使用前需要替换成你的外部驱动器的设备实例ID # 获取方式:设备管理器 -> 找到你的外部驱动器 -> 属性 -> 详细信息 -> 设备实例路径 # eject_drive("USBSTOR\\DISK&VEN_SANDISK&PROD_CRUZER_GLIDE&REV_1.27\\1234567890ABCDEF&0")
注意事项
- 设备实例ID是固定的(同一台设备同一USB口),可以提前获取后硬编码到脚本里
- 同样需要确保备份文件完全写入后再执行弹出操作
内容的提问来源于stack exchange,提问作者some1and2
相关产品推荐
相关产品推荐

