且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何使用python检查磁盘是否在驱动器中?

更新时间:2023-11-28 09:59:04

和许多事情一样,答案在 十年前关于 C++/Win32 编程的文章.

And the answer, as with so many things, turns out to be in an article about C++/Win32 programming from a decade ago.

简而言之,问题在于 Windows 处理软盘错误的方式与其他类型的驱动器错误略有不同.默认情况下,无论您的程序做什么,或认为它在做什么,Windows 都会拦截设备抛出的任何错误并向用户显示一个对话框,而不是让程序处理它 - 确切的问题我有.

The issue, in a nutshell, is that Windows handles floppy disk errors slightly differently than other kinds of drive errors. By default, no matter what you program does, or thinks it's doing, Windows will intercept any errors thrown by the device and present a dialog box to the user rather than letting the program handle it - the exact issue I was having.

但是,事实证明,有一个 Win32 API 调用来解决这个问题,主要是 SetErrorMode()

But, as it turns out, there's a Win32 API call to solve this issue, primarily SetErrorMode()

简而言之(我在这里提供了很多细节),我们可以使用 SetErrorMode() 来让 Windows 不再如此偏执,做我们的事情,让程序会处理这种情况,然后将 Windows 错误模式重置回之前的状态,就好像我们从未出现过一样.(这里可能有一个 Keyser Soze 的玩笑,但我今天摄入的咖啡因量不对,无法找到它.)

In a nutshell (and I'm handwaving a way a lot of the details here), we can use SetErrorMode() to get Windows to stop being quite so paranoid, do our thing and let the program handle the situation, and then reset the Windows error mode back to what it was before as if we had never been there. (There's probably a Keyser Soze joke here, but I've had the wrong amount of caffeine today to be able to find it.)

改编链接文章中的 C++ 示例代码,如下所示:

Adapting the C++ sample code from the linked article, that looks about like this:

int OldMode; //a place to store the old error mode
//save the old error mode and set the new mode to let us do the work:
OldMode = SetErrorMode(SEM_FAILCRITICALERRORS); 
// Do whatever we need to do that might cause an error
SetErrorMode(OldMode); //put things back the way they were

在 C++ 下,以正确的方式检测错误需要 `GetLastError()' 函数,幸运的是我们在这里不需要担心,因为这是一个 Python 问题.在我们的例子中,Python 的异常处理工作正常.那么,这就是我拼凑起来检查驱动器号是否就绪"的功能,如果其他人需要,所有这些都准备好复制粘贴:

Under C++, detecting errors the right way needs the `GetLastError()' function, which we fortunately don't need to worry about here, since this is a Python question. In our case, Python's exception handling works fine. This, then, is the function I knocked together to check a drive letter for "readiness", all ready for copy-pasting if anyone else needs it:

import win32api
def testDrive( currentLetter ):
    """
    Tests a given drive letter to see if the drive is question is ready for 
    access. This is to handle things like floppy drives and USB card readers
    which have to have physical media inserted in order to be accessed.
    Returns true if the drive is ready, false if not.
    """
    returnValue = False
    #This prevents Windows from showing an error to the user, and allows python 
    #to handle the exception on its own.
    oldError = win32api.SetErrorMode( 1 ) #note that SEM_FAILCRITICALERRORS = 1
    try:
        freeSpace = win32file.GetDiskFreeSpaceEx( letter )
    except:
        returnValue = False
    else:
        returnValue = True
    #restore the Windows error handling state to whatever it was before we
    #started messing with it:
    win32api.SetErrorMode( oldError )
    return returnValue

最近几天我一直在使用它,它对软盘和 USB 读卡器都运行良好.

I've been using this quite a bit the last few days, and it's been working beautifully for both floppies and USB card readers.

一些注意事项:几乎所有需要磁盘访问的函数都可以在 try 块中运行 - 由于媒体不存在,我们正在寻找的所有异常都存在.

A few notes: pretty much any function needing disk access will work in the try block - all we're looking for in an exception due to the media not being present.

此外,虽然 python win32api 包公开了我们需要的所有函数,但它似乎没有任何标志常量.在翻遍了 MSDN 的古老肠道之后,结果发现 SEM_FAILCRITICALERRORS 等于 1,这让我们的生活变得非常轻松.

Also, while the python win32api package exposes all the functions we need, it dones't seem to have any of the flag constants. After a trip to the ancient bowels of MSDN, it turns out that SEM_FAILCRITICALERRORS is equal to 1, which makes our life awfully easy.

我希望这能帮助其他有类似问题的人!

I hope this helps someone else with a similar problem!