4

我正在尝试使用 ReadDirectoryChangesW API 使用 Python 在 Windows 上查看创建/删除/重命名更改的目录。这是我的代码,它工作正常:

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的解决方案,但没有帮助。

提前致谢!

4

3 回答 3

3

这篇博文

[ReadDirectoryChangesW] 的另一个潜在缺陷是引用的目录本身现在“正在使用”,因此无法删除。要监视目录中的文件并仍然允许删除该目录,您必须监视父目录及其子目录。

该帖子还提供了有关正确使用 ReadDirectoryChangesW 的更多详细信息

于 2011-07-27T03:57:19.113 回答
2

可以在下面删除监视的文件ReadDirectoryChangesW

Jim Beveridge 的“Understanding ReadDirectoryChangesW - Part 2”(正如 Artomegus 所提到的)是解决这个问题的一个很好的背景,但是解释FILE_SHARE_DELETE用法的声明具有误导性。

我的测试,FILE_SHARE_DELETE实际上允许删除/重命名监视文件夹。(换句话说,您不需要将“监视父文件夹”作为唯一选项。)

这是工作片段(编辑并大量借鉴了 Tim Golden 的这篇出色的“Watch a Directory for Changes”)

# 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
于 2012-09-10T04:16:31.033 回答
0

好的,解决这个问题并不简单......在我的情况下(http://www.themacaque.com/?p=859)我忽略了允许重命名或删除目录的事实。

允许用户重命名监视文件夹的方法是使用路径祖先上的 ReadDirectoryChangesW 来监视并根据您正在监视的路径过滤事件。我已经实现了一种新的方法来执行使用 twisted 来执行事件处理的监视。使用该解决方案,您可以在以下情况下观察祖先:

  1. 您的文件夹没有太多可以忽略的兄弟。您不希望执行大量操作来过滤您不感兴趣的事件。
  2. 如果用户无法删除祖先,则没有问题。

在 Windows 上的 Ubuntu One 的代码中,我们一直在处理这个问题,我们已经实现了一个很好的解决方案,您可以看看。它遵循了 linux 上 pyinotify 的一些实现,它带有一个处理器,允许您使用回调挂钩一个对象,该回调将根据扭曲反应堆主循环中的事件被调用。看看那个代码,它可能对你有帮助。

在我的博客或 irc 中(在#ubuntuone 或 #pyar 的 freenode 中)我知道任何问题,我的昵称是 mandel ;)

于 2011-07-30T15:10:36.197 回答