如何用Python检查磁盘是否在驱动器中?
假设我想在软盘驱动器或USB读卡器上操作一些文件。那我怎么检查这个驱动器是否准备好了呢?(也就是说,里面是否插入了磁盘。)
驱动器的字母是存在的,所以用os.exists()检查时总是会返回True。在这个过程中,我还不知道任何文件名,所以检查某个文件是否存在也没用。
再解释一下:这里的问题是异常处理。大多数win32 API调用在你尝试访问一个未准备好的驱动器时会抛出一个异常。通常,这样做是没问题的——你可以查看一下可用空间,然后捕获这个异常,假设这意味着没有磁盘在里面。然而,即使我捕获了所有的异常,Windows仍然会弹出一个讨厌的错误对话框,告诉我软盘/读卡器没有准备好。所以,我想真正的问题是——我怎么才能不让这个Windows错误框弹出来呢?
6 个回答
如果你有pythonwin,这里有一个链接,里面的信息可能对你有帮助:这个教程。
我猜“可用性”和“状态”这两个方面可能值得关注。或者你可以测试一下卷标名称,我想如果驱动器里没有东西,它可能会显示'X:'或者是空的。或者,干脆看看剩余空间或者总的块数。
你可以用 len(os.listdir("path"))
来判断这个文件夹里有没有文件。如果结果是零,那就说明这个文件夹里没有文件。
答案其实和很多事情一样,来源于一篇十年前关于C++/Win32编程的文章。
简单来说,问题在于Windows处理软盘错误的方式和其他类型的驱动器错误稍有不同。默认情况下,不管你的程序在做什么,或者认为自己在做什么,Windows都会拦截设备抛出的任何错误,并弹出一个对话框给用户,而不是让程序自己处理这个错误——这正是我遇到的问题。
不过,事实证明,有一个Win32 API调用可以解决这个问题,主要是SetErrorMode()
。
简单来说(这里我省略了很多细节),我们可以使用SetErrorMode()
来让Windows不要那么紧张,先让程序自己处理情况,然后再把Windows的错误模式恢复到之前的状态,就好像我们从未出现过一样。(这里可能有个关于Keyser Soze的笑话,但今天我喝的咖啡量不太对,找不到那个笑话。)
根据链接文章中的C++示例代码,大致是这样的:
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的异常处理就很好用。因此,我写了这个函数来检查驱动器字母是否“准备好”,如果有人需要,可以直接复制粘贴:
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读卡器。
几点说明:几乎任何需要磁盘访问的函数都可以放在try块中——我们只是在寻找由于媒体不存在而引发的异常。
另外,虽然Python的win32api
包提供了我们需要的所有函数,但似乎没有任何标志常量。经过一番查找,发现SEM_FAILCRITICALERRORS等于1,这让我们的工作轻松多了。
希望这能帮助到其他有类似问题的人!