2011-07-26 4 views
3

J'essaie de regarder un répertoire pour créer/supprimer/renommer des modifications sur Windows avec python en utilisant l'API ReadDirectoryChangesW. Ceci est mon code et il fonctionne très bien:ReadDirectoryChangesW bloque la suppression du répertoire surveillé

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) 

Cependant, lorsque je tente de supprimer le dossier surveillé de python ou de l'explorateur windows, je reçois:

WindowsError: [Erreur 32] Le processus ne peut pas accéder au fichier car il est utilisé par un autre processus: « c: \ users \ user \ AppData \ temp local \ \ new_dir »

Je crois que cela a du sens, mais comment dois-je résoudre ce problème? Parce que mon application devrait permettre à l'utilisateur de supprimer un dossier surveillé. J'ai essayé la solution pour la méthode asynchrone http://www.themacaque.com/?p=859, mais cela n'a pas aidé.

Merci d'avance!

Répondre

3

De 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.

Le poste fournit également quelques détails sur l'utilisation correcte des ReadDirectoryChangesW

+1

Merci pour votre réponse, je trouve ce poste mais apparemment manqué ce bloc. – Mohamad

0

Ok, ce n'est pas simple à résoudre ... Dans mon cas (http: // www.themacaque.com/?p=859) J'ai ignoré le fait de permettre de renommer ou supprimer le répertoire. Ce que vous pouvez faire pour permettre à l'utilisateur de renommer le dossier de surveillance est d'utiliser ReadDirectoryChangesW sur l'ancêtre du chemin pour regarder et filtrer les événements en fonction des chemins que vous regardez. J'ai mis en place une nouvelle façon d'effectuer l'observation en utilisant twisted pour effectuer le traitement des événements. Avec cette solution vous pourriez être wathching les ancêtres si:

  1. Vous dossier n'a pas trop de frères à ignorer. Vous ne voulez pas effectuer beaucoup, beaucoup d'opérations pour filtrer les événements qui ne vous intéressent pas.
  2. Il n'y a pas de problème si l'utilisateur ne peut pas supprimer l'ancêtre.

Dans le code d'Ubuntu One sur Windows, nous avons traité ce problème et nous avons implémenté une solution intéressante que vous pouvez consulter. Il s'ensuit un peu l'implémentation de pyinotify sur linux avec un processeur qui va vous permettre d'accrocher un objet avec des callbacks qui seront appelés en fonction de l'évènement dans la boucle principale des réacteurs torsadés. Jetez un oeil à ce code, il pourrait vous aider.

Tout problème en retard me connaissent soit dans mon blog ou irc (en freenode à #ubuntuone ou #pyar) mon surnom est mandel;)

1

Suppression du dossier surveillé IS possible sous ReadDirectoryChangesW

"Understanding ReadDirectoryChangesW - Part 2" by Jim Beveridge est (comme Artomegus mentionné) un très bon arrière-plan pour ce problème, mais l'instruction expliquant FILE_SHARE_DELETE utilisation est trompeuse.

A mes tests, l'utilisation de FILE_SHARE_DELETE permet en réalité de supprimer/renommer le dossier surveillé. (En d'autres termes, vous n'avez pas besoin de "regarder le dossier parent" comme seule option.)

Voici l'extrait de travail (édité et largement emprunté de ce par ailleurs excellent "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 
Questions connexes