2014-12-23 1 views
2

Я создаю относительно простое приложение, которое запрашивает каталоги, проверяет, правильны ли они, а затем удаляет один из них и воссоздает его с содержимым другого. Я сталкиваюсь с этим странным поведением, я попытаюсь объяснить:Может ли кто-нибудь объяснить это странное поведение shutil.rmtree и shutil.copytree?

Когда у меня открыто окно папки назначения, и оно пустое, есть исключение, запрещенное доступом, после чего меня выталкивают из папки, и это удаляется. Но тогда, если он не пуст, он работает отлично, никаких исключений, целевой каталог (из того, что кажется) становится опустошенным, а затем заполнен файлами из исходного каталога. Что странно, потому что он должен прямо удалять папку назначения, несмотря ни на что, а затем воссоздать ее с тем же именем и содержимым из источника.

Это не имеет смысла для меня, разве не должно быть такого же исключения, когда я просматриваю каталог, когда он не пуст, как когда он пуст? В чем разница, все равно предполагается удалить папку. Есть ли логическое объяснение этому? Кроме того, если есть исключение, почему каталог удаляется в любом случае?

Код для этой конкретной части довольно проста (пожалуйста, имейте в виду, я новичок :))

def Delete(self, dest): 

    try: 
     shutil.rmtree(dest) 
     self.Paste(self.src, dest) 
    except (IOError, os.error) as e: 
     print e 

def Paste(self, src, dest): 

    try: 
     shutil.copytree(src, dest) 
    except (IOError, os.error) as e: 
     print e 
+1

Получаете ли вы исключение, запрещенное доступом, из 'Delete()' или 'Paste()'? Трудно сказать, когда в блоке 'try' есть несколько операторов. Лучше всего добавить всю трассировку вашего вопроса. Обязательно отложите его на 4 пробела, чтобы он был доступен для чтения. – martineau

ответ

1

Это ожидаемое поведение на Windows.

Внутренний номер shutil.rmtree вызывает функцию API окон DeleteFile, которая задокументирована на MSDN (http://msdn.microsoft.com/en-us/library/windows/desktop/aa363915%28v=vs.85%29.aspx).

Эта функция обладает свойством (Highlite мной):

Функция DeleteFile помечает файл для удаления при закрытии. Следовательно, удаление файла не происходит до тех пор, пока последний дескриптор файла не будет закрыт. Последующие вызовы CreateFile, чтобы открыть файл, не работают с ERROR_ACCESS_DENIED.

Если какой-либо другой процесс по-прежнему открыт ручкой (например, антивирусные сканеры, проводник Windows, потому что вы смотрите каталог или что-то еще, у которого еще может быть дескриптор этого каталога), он не исчезнет.

Обычно вы просто перехватываете исключение в своей операции Вставить и несколько раз повторяете его/за несколько миллисекунд, чтобы обрабатывать все эти странные аномалии антивируса.

Маленький бонус: вы можете использовать windbg или ProcessExplorer, чтобы узнать, кто все еще держит открытый дескриптор вашего файла (просто используйте Find Handle в Process explorer и найдите имя файла).

+0

Хорошо, но это все еще не объясняет, почему нет проблем, когда каталог не пуст, что меня больше смущает. Еще раз: программа должна удалить каталог независимо от того, что. Когда я наблюдаю за каталогом в проводнике Windows, и он пуст, есть исключение, но если оно не пустое, тогда нет никаких проблем, и я могу наблюдать, как файлы вставляются, в то время как папка якобы удаляется и воссоздано – zephi

+0

Ну, это состояние гонки.Если каталог пуст, у вас есть кратчайший возможный случай (только один 'DeleteFile'), если он не пуст, код shutil будет рекурсивно удалять множество файлов и каталогов, поэтому у исследователя будет больше времени, чтобы избавиться от дескриптора перед тем, как произойдет следующий вызов 'CreateFile'. Если вы действительно хотите знать, что произойдет, вам нужно будет использовать windbg и выполнить некоторую отладку на уровне ядра. – schlenk

 Смежные вопросы

  • Нет связанных вопросов^_^