ReadDirectoryChangesW блокирует удаление просматриваемого каталога - PullRequest
4 голосов
/ 26 июля 2011

Я пытаюсь посмотреть каталог для создания / удаления / переименования изменений в windows с python, используя API ReadDirectoryChangesW. Это мой код, и он работает нормально:

results = win32file.ReadDirectoryChangesW(self.hDir, 8192, True, self.type, None,
                                           None)
for action, file in results:
    full_filename = os.path.join (self.source_path, file)
    if   action == 1:                                    # Created
        self.fileCreated(full_filename)
    elif action == 2:                                    # Deleted
        self.fileDeleted(full_filename)
    elif action == 3:                                    # Updated
        self.fileUpdated(full_filename)
    elif action == 4:                                    # Renamed from something
        renamed_file = full_filename
    elif action == 5:                                    # Renamed to something
        self.fileRenamed(renamed_file, full_filename)

Однако, когда я пытаюсь удалить отслеживаемую папку из python или из проводника Windows, я получаю:

WindowsError: [Ошибка 32] Процесс не может получить доступ к файлу, поскольку он используется другим процессом: 'c: \ users \ user \ appdata \ local \ temp \ new_dir'

Я считаю, что это имеет смысл, но как мне решить это? Потому что мое приложение должно позволять пользователю удалять просматриваемые папки. Я попробовал решение для асинхронного метода http://www.themacaque.com/?p=859,, но это не помогло.

Заранее спасибо!

Ответы [ 3 ]

3 голосов
/ 27 июля 2011

С этого блога :

Другая потенциальная ловушка [ReadDirectoryChangesW] заключается в том, что сам ссылочный каталог сейчас «используется» и поэтому не может быть удален. Чтобы отслеживать файлы в каталоге и все еще разрешать удаление каталога, вам придется отслеживать родительский каталог и его дочерние элементы.

В посте также приведены некоторые подробности о правильном использовании ReadDirectoryChangesW

2 голосов
/ 10 сентября 2012

Удаление просматриваемой папки IS возможно в ReadDirectoryChangesW

«Понимание ReadDirectoryChangesW - Часть 2» Джима Бевериджа является (как упоминал Артемегус) очень хорошим фоном для этой проблемы, но утверждение, объясняющее использование FILE_SHARE_DELETE, вводит в заблуждение.

В моих тестах использование FILE_SHARE_DELETE фактически позволяет удалять / переименовывать просматриваемые папки. (Другими словами, вам не нужно «смотреть родительскую папку» как единственный вариант.)

Вот рабочий фрагмент (отредактированный и заимствованный из этого, в остальном превосходного «Следи за изменениями» Тима Голдена

# License is same as snippets on this page
# http://timgolden.me.uk/python/win32_how_do_i/watch_directory_for_changes.html
# In other words, bug Tim Golden to publish a license for his snippets
def windows_watch_path(watched_path):
    import win32file
    import win32con

    ACTIONS = {
        1 : "Created",
        2 : "Deleted",
        3 : "Updated",
        4 : "RenamedFrom",
        5 : "RenamedTo"
    }
    # Thanks to Claudio Grondi for the correct set of numbers
    FILE_LIST_DIRECTORY = 0x0001

    try:
        hDir = win32file.CreateFile (
            watched_path
            , FILE_LIST_DIRECTORY
            , win32con.FILE_SHARE_READ | 
              win32con.FILE_SHARE_WRITE | 
              win32con.FILE_SHARE_DELETE
            , None
            , win32con.OPEN_EXISTING
            , win32con.FILE_FLAG_BACKUP_SEMANTICS
            , None
        )
    except:
        # either it does not exist by this time, or some other issue... blah.
        # we'll just say "it 'changed' from 'some other expected state'"
        return [[watched_path, '', ACTIONS[2]]]

    results = win32file.ReadDirectoryChangesW (
        hDir,
        1024,
        True,
        win32con.FILE_NOTIFY_CHANGE_FILE_NAME |
        win32con.FILE_NOTIFY_CHANGE_DIR_NAME |
        win32con.FILE_NOTIFY_CHANGE_ATTRIBUTES |
        win32con.FILE_NOTIFY_CHANGE_SIZE |
        win32con.FILE_NOTIFY_CHANGE_LAST_WRITE |
        win32con.FILE_NOTIFY_CHANGE_SECURITY,
        None,
        None
    )

    files_changed = []
    for action, fn in results:
        files_changed.append(
            [
                watched_path
                , fn
                , ACTIONS[action]
            ]
        )
        # print fullfn, ACTIONS.get(action, "Unknown")
    return files_changed
0 голосов
/ 30 июля 2011

Хорошо, это не просто решить ... В моем случае (http://www.themacaque.com/?p=859) я проигнорировал факт разрешения переименовывать или удалять каталог.

То, что вы можете сделать, чтобы позволить пользователю переименовать папку наблюдения, - это использовать ReadDirectoryChangesW на предке пути для просмотра и фильтрации событий в соответствии с путями, которые вы смотрите. Я реализовал новый способ выполнения наблюдения с использованием витой для обработки событий. С этим решением вы могли бы наблюдать за предками, если:

  1. В вашей папке не слишком много братьев, чтобы их игнорировать. Вы не хотите выполнять множество операций для фильтрации событий, которые вас не интересуют.
  2. Нет проблем, если пользователь не может удалить предка.

В коде Ubuntu One на окнах мы имели дело с этой проблемой, и мы реализовали хорошее решение, на которое вы можете взглянуть. Немного следует за реализацией pyinotify на linux с процессором, который позволит вам перехватить объект обратными вызовами, которые будут вызываться в соответствии с событием в основном цикле витых реакторов. Посмотрите на этот код, он может вам помочь.

Любую проблему поздно я знаю либо в моем блоге, либо в irc (во freenode на #ubuntuone или #pyar) мой псевдоним mandel;)

...