2013-08-19 63 views
0

我想監視目錄,而目錄有子顯示目錄和子目錄中有與.md薩姆文件。 (也許還有其他的一些文件,如* .SWP ...)蟒蛇pyinotify中監視指定後綴的文件在目錄

我只想監控.MD文件,我看了文檔,而且只有一個ExcludeFilter,並在問題:https://github.com/seb-m/pyinotify/issues/31說,只有目錄可以過濾,但不是文件。

現在我所做的是在process_*函數中進行過濾,通過fnmatch檢查event.name

所以,如果我只是想監視指定後綴的文件,有沒有更好的辦法?謝謝。

這是我寫的主要代碼:

!/usr/bin/env python                                 
# -*- coding: utf-8 -*- 

import pyinotify                  
import fnmatch                  

def suffix_filter(fn):                
    suffixes = ["*.md", "*.markdown"]                             
    for suffix in suffixes:               
     if fnmatch.fnmatch(fn, suffix):            
      return False                
    return True                  

class EventHandler(pyinotify.ProcessEvent):           
    def process_IN_CREATE(self, event):            
     if not suffix_filter(event.name):           
      print "Creating:", event.pathname          

    def process_IN_DELETE(self, event):            
     if not suffix_filter(event.name):           
      print "Removing:", event.pathname          

    def process_IN_MODIFY(self, event):            
     if not suffix_filter(event.name):           
      print "Modifing:", event.pathname          

    def process_default(self, event):            
     print "Default:", event.pathname 

回答

2

我想你基本上正確的想法,但它可以更容易地實現。

ProcessEventpyinotify這個模塊已經有一個鉤子可以用來過濾事件的處理。它通過調用構造函數時給出的可選pevent關鍵字參數指定,並保存在實例的self.pevent屬性中。默認值是None。它的值是在類__call__()方法用作顯示從pyinotify.py源文件中的以下片段:

def __call__(self, event): 
    stop_chaining = False 
    if self.pevent is not None: 
     # By default methods return None so we set as guideline 
     # that methods asking for stop chaining must explicitly 
     # return non None or non False values, otherwise the default 
     # behavior will be to accept chain call to the corresponding 
     # local method. 
     stop_chaining = self.pevent(event) 
    if not stop_chaining: 
     return _ProcessEvent.__call__(self, event) 

所以,你可以用它只允許某些後綴(又名擴展)用這樣的文件的事件:

SUFFIXES = {".md", ".markdown"} 

def suffix_filter(event): 
    # return True to stop processing of event (to "stop chaining") 
    return os.path.splitext(event.name)[1] not in SUFFIXES 

processevent = ProcessEvent(pevent=suffix_filter) 
+0

我之前曾經評論說我無法讓這個工作,但現在我明白了。你需要編輯'SUFFIXES'並移除'*'(否則它永遠不會匹配),並在'fn.name'上調用'splitext',因爲'pevent'可調用將'Event'作爲參數。 +1,比我的解決方案更好,我實際上試圖用'pevent'解決這個問題,但由於某種原因無法使用它。 –

+0

非常感謝,這種方式太酷了!代碼中有一點錯誤。當使用'suffix_filter'作爲'pevent'的回調函數時,suffix_filter的參數是一個'event',所以它應該是'os.path.splitext(fn.name)[1]' –

+0

Tanky,@Paulo:謝謝指出編碼錯誤。只要有可能,我不會發布未經測試的東西,但不能在這種情況下,因爲我的操作系統沒有inotify。 – martineau

1

有沒有什麼特別的問題與您的解決方案的,但你希望你的inotify處理程序要儘可能地快,所以有一些優化可以使。

你應該將你的比賽後綴出你的函數,所以編譯器只建立過一次:

EXTS = set([".md", ".markdown"]) 

我讓他們一組,所以你可以做一個更有效的匹配:

def suffix_filter(fn): 
    ext = os.path.splitext(fn)[1] 
    if ext in EXTS: 
    return False 
    return True 

我只假設os.path.splitext和一組搜索比迭代fnmatch更快,但對於您的一小部分擴展名,這可能並非如此 - 您應該測試它。 (注意:我已經在上面鏡像了你的代碼,當你進行比賽時你會返回False,但我不相信這就是你想要的 - 對於閱讀你的代碼的人來說,至少不是很清楚)

+0

Tanky你。我之前並不知道'set'中的'in'操作比'list'快,ref:http://stackoverflow.com/questions/2831212/python-sets-vs-lists。關於你的說明:我想過濾不符合指定的後綴,所以何時過濾,我返回True,有什麼辦法可以讓它清楚嗎? –

1

您可以使用ProcessEvent__call__方法調用集中到suffix_filter

class EventHandler(pyinotify.ProcessEvent): 
    def __call__(self, event): 
     if not suffix_filter(event.name): 
      super(EventHandler, self).__call__(event) 

    def process_IN_CREATE(self, event): 
     print "Creating:", event.pathname 

    def process_IN_DELETE(self, event): 
     print "Removing:", event.pathname 

    def process_IN_MODIFY(self, event): 
     print "Modifying:", event.pathname 
+0

謝謝!你和@ martineau的方式都非常酷! –