2011-07-26 50 views
3

我想用python使用ReadDirectoryChangesW 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

this blog post

Another potential pitfall of [ReadDirectoryChangesW] is that the referenced directory itself is now "in use" and so can't be deleted. To monitor files in a directory and still allow the directory to be deleted, you would have to monitor the parent directory and its children.

该帖子还提供了关于正确使用ReadDirectoryChangesW

+1

谢谢您的回答!我发现后,但显然错过了块编辑和大量举债。 – Mohamad

0

好一些细节,这不是简单的解决......在我的情况(HTTP:// www.themacaque.com/?p=859)我忽略了允许重命名或删除目录的事实。

允许用户重命名监视文件夹的方法是使用路径祖先上的ReadDirectoryChangesW根据您正在观看的路径观看和过滤事件。我已经实施了一种使用扭曲来执行观看处理的新方法。有了这个解决方案,您可以在以下情况下扫描祖先:

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

在Ubuntu One的代码中,我们一直在处理这个问题,并且我们已经实现了一个很好的解决方案,您可以查看一下。在linux上使用pyinotify实现一个处理器,它允许你用一个回调函数来挂钩一个对象,这个回调函数将根据双绞线主环路中的事件被调用。看看这些代码,它可能会帮助你。

任何问题下旬我知道,无论是在我的博客或IRC(Freenode的在#ubuntuone或#pyar)我的昵称是曼德尔;)

1

删除监视文件夹IS可能ReadDirectoryChangesW

"Understanding ReadDirectoryChangesW - Part 2" by Jim Beveridge是(如Artomegus提到的)这个问题的一个很好的背景,但解释FILE_SHARE_DELETE使用的说法是误导。

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

这里是工作段(从这个否则优秀"Watch a Directory for Changes" by Tim Golden

# 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