И ответ, как и во многих других вещах, оказывается в статье о программировании на C ++ / Win32 десятилетия назад .
Вкратце, проблема в том, что Windows обрабатывает ошибки гибких дисков немного иначе, чем другие виды ошибок дисков. По умолчанию, независимо от того, что ваша программа делает, или думает , что она делает, Windows будет перехватывать любые ошибки, выдаваемые устройством, и отображать диалоговое окно для пользователя, а не позволять программе ее обрабатывать - точная проблема, которую я имел.
Но, как выясняется, существует вызов Win32 API для решения этой проблемы, в первую очередь SetErrorMode()
В двух словах (и я подробно описываю здесь много деталей), мы можем использовать SetErrorMode()
, чтобы заставить Windows перестать быть настолько параноиком, сделаем свое дело и позволим программе справиться с ситуацией, и затем сбросьте режим ошибок Windows обратно к тому, что был раньше, как будто мы никогда там не были. (Возможно, здесь есть шутка с Кайзером Созе, но сегодня у меня было неправильное количество кофеина, чтобы найти его.)
Адаптация примера кода 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
предоставляет все необходимые функции, он, похоже, не имеет каких-либо констант флагов. После поездки в древние недра MSDN оказалось, что SEM_FAILCRITICALERRORS равен 1, что делает нашу жизнь ужасно легкой.
Надеюсь, это поможет кому-то еще с подобной проблемой!