2013-08-19 1 views
0

dir을 모니터링하고 dir에 하위 디렉토리가 있고 subdir에 .md 인 somes 파일이 있습니다. 나는이 문서를 읽고,Python pyinotify를 사용하여 특정 접미사 파일을 모니터 할 수 있습니다.

나는 단지 .md 파일을 모니터링 할 (아마도 ... 등 * .swp 같은 다른 파일이 있습니다), 거기 만 ExcludeFilter이며, 문제의 : https://github.com/seb-m/pyinotify/issues/31 말하지만, dir 만 필터가 될 수 있지만 파일은 아닙니다.

이제 필터를 process_*에 입력하고 event.name을 확인하여 fnmatch으로 확인하십시오.

그래서 지정된 접미사 파일 만 모니터링하려는 경우 더 좋은 방법이 있습니까? 감사.

이 내가 쓴 주요 코드 :

!/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

난 당신이 기본적으로 올바른 생각을 가지고 있지만,보다 쉽게 ​​구현 될 수 있다고 생각합니다.

pyinotify 모듈의 ProcessEvent 클래스는 이미이 사건의 처리를 필터링하는 데 사용할 수있는 후크가 있습니다. 선택자 pevent 키워드 인수를 통해 지정되며 생성자에 대한 호출에서 제공되며 인스턴스의 self.pevent 속성에 저장됩니다. 기본값은 None입니다.

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) 

그래서 당신은 이런 일에 특정 접미사 (일명 확장)를 가진 파일에 대한 이벤트를 할 수 그것을 사용할 수 있습니다 : 그것은 pyinotify.py 소스 파일에서 다음 코드에서와 같이 값이 클래스의 __call__() 방법에 사용되어 있어요 :

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

나는 이전에 내가 이것을 작동시키지 못한다고 말했지만 이제는 얻었습니다. 'pevent' 호출 가능 변수가'Event'를 매개 변수로 취하기 때문에'SUFFIXES'을 편집하고'*'(그렇지 않으면 결코 일치하지 않습니다)를 제거하고'fn.name'에서'splitext'를 호출해야합니다. +1, 내 솔루션보다 좋네, 그리고 실제로는 'pevent'로 해결하려고했지만 어떤 이유로 작동하지 못했습니다. –

+0

대단히 고맙습니다. 이쪽은 정말 멋집니다! 코드에 약간의 오류가 있습니다. suffix_filter를'pevent'에 대한 콜백으로 사용할 때 suffix_filter의 인수는'event'이므로'os.path.splitext (fn.name) [1]'이어야합니다 –

+0

Tanky, @Paulo : 가리키는 것에 감사드립니다 코딩 오류를 밖으로. 가능할 때마다 테스트되지 않은 항목은 게시하지 않지만 내 OS에는 inotify가 없기 때문에이 경우에는 실행할 수 없습니다. – martineau

1

이 솔루션 특히 아무 문제가 없다, 그러나 당신이 당신의 inotify를 핸들러가 가능한 한 빨리되고 싶어요, 그래서 당신이 할 수있는 몇 가지 최적화가 .

당신은 당신의 기능에서 당신의 경기 접미사를 이동해야하므로 컴파일러는 한 번만를 구축 :

def suffix_filter(fn): 
    ext = os.path.splitext(fn)[1] 
    if ext in EXTS: 
    return False 
    return True 
: 나는 그들에게 세트를 만들어

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

좀 더 효율적인 경기를 할 수 있도록

나는 단지 os.path.splitext과 설정 한 검색이 반복적 인 fnmatch보다 빠르다고 추정하고 있습니다 만, 이것은 정말로 작은 확장 목록에 해당하지 않을 수 있습니다. 테스트해야합니다.

(참고 : 일치하는 항목을 False로 반환 한 곳에서 코드를 미러링했지만, 사용자가 원하는 내용을 확신하지 못했습니다. 코드를 읽는 사람에게 분명히 분명하지 않습니다.

+0

Tanky you. 나는'set'에서'in' 연산이'list'보다 빠르다는 것을 알지 못했습니다. ref : http://stackoverflow.com/questions/2831212/python-sets-vs-lists. 노트 정보 : 지정된 것과 일치하지 않는 접미사를 필터링하고 싶습니다. 필터를 적용 할 때 True를 반환합니다. 명확하게 할 수있는 방법이 있습니까? –

1

당신은 suffix_filter에 전화를 중앙 집중화 ProcessEvent__call__ 방법을 사용할 수 있습니다 :

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

감사합니다.당신과 @ 마티노의 방법은 모두 아주 멋지다! –

관련 문제