2010-06-18 3 views
4

변경에 대한 디렉토리 모니터링 할 GIO FileMonitor를 사용합니다 (이 질문에 대한 GIO answer에서) 다음 데모 코드를 가지고 :이 코드를 실행 한 후PyGTK/GIO : 변경을위한 모니터 디렉토리는 재귀 적으로

import gio 

def directory_changed(monitor, file1, file2, evt_type): 
    print "Changed:", file1, file2, evt_type 

gfile = gio.File(".") 
monitor = gfile.monitor_directory(gio.FILE_MONITOR_NONE, None) 
monitor.connect("changed", directory_changed) 

import glib 
ml = glib.MainLoop() 
ml.run() 

을, 그런 다음 하위 노드를 만들고 수정하고 변경 사항을 알릴 수 있습니다. 그러나 이는 직접적인 어린이들에게만 작용합니다 (나는 문서가 다른 말을하지 않는다는 것을 알고 있습니다). 다음 셸 명령 중 마지막 명령은 알림을 표시하지 않습니다.

touch one 
mkdir two 
touch two/three 

쉽게 재귀 적으로 만들 수있는 방법이 있습니까? 차라리 직접 디렉토리 생성을 찾고 모니터를 추가하고 삭제시 삭제하는 등의 수동 코딩을하지 않을 것입니다.

의도 된 용도는 VCS 파일 브라우저 확장 프로그램에서 파일의 상태를 캐시 할 수 있습니다. 작업 복사본을 만들고 변경 사항을 개별적으로 업데이트하십시오. 따라서 수십에서 수천 (또는 그 이상의) 디렉토리를 모니터링 할 수 있습니다. 작업 복사본의 루트를 찾고 거기에 파일 모니터를 추가하고 싶습니다.

나는 약 pyinotify을 알고 있지만, FreeBSD 또는 기타와 같은 비 Linux 커널에서 작동하도록 피하고 있습니다. 내가 아는 한, GIO FileMonitor는 사용 가능한 곳에서 inotify를 사용하며 어느 정도의 추상화를 유지하기 위해 구현을 강조하지 않고 이해할 수 있지만 가능한 것이어야한다고 제안했습니다.

(여기서 내가 원래 PyGTK mailing list에 게시, 중요.)

답변

1

는 잘 모르겠지만, 그것 않는 경우이 같은 것을 할 수 없어 더 * 이유가 없습니다 :

import gio 
import os 

def directory_changed(monitor, file1, file2, evt_type): 
    if os.path.isdir(file2): #maybe this needs to be file1? 
     add_monitor(file2) 
    print "Changed:", file1, file2, evt_type 

def add_monitor(dir): 
    gfile = gio.File(dir) 
    monitor = gfile.monitor_directory(gio.FILE_MONITOR_NONE, None) 
    monitor.connect("changed", directory_changed) 

add_monitor('.') 

import glib 
ml = glib.MainLoop() 
ml.run() 

을 * 내가 말 아무 이유없이 GIO에 대한 지식이 거의 없기 때문에 이것이 리소스 호그가 될 가능성이 있습니다. 몇 가지 명령 (다른 것들 중에서 os.listdir)을 사용하여 파이썬에서 자신의 것을 롤백하는 것도 전적으로 가능합니다.

import time 
import os 

class Watcher(object): 
    def __init__(self): 
     self.dirs = [] 
     self.snapshots = {} 

    def add_dir(self, dir): 
     self.dirs.append(dir) 

    def check_for_changes(self, dir): 
     snapshot = self.snapshots.get(dir) 
     curstate = os.listdir(dir) 
     if not snapshot: 
      self.snapshots[dir] = curstate 
     else: 
      if not snapshot == curstate: 
       print 'Changes: ', 
       for change in set(curstate).symmetric_difference(set(snapshot)): 
        if os.path.isdir(change): 
         print "isdir" 
         self.add_dir(change) 
        print change, 

       self.snapshots[dir] = curstate 
       print 

    def mainloop(self): 
     if len(self.dirs) < 1: 
      print "ERROR: Please add a directory with add_dir()" 
      return 

     while True: 
      for dir in self.dirs: 
       self.check_for_changes(dir) 
      time.sleep(4) # Don't want to be a resource hog 

w = Watcher() 
w.add_dir('.') 


w.mainloop() 
+0

이것은 나에게 정말 좋은 출발점을주었습니다. 덕분에 :) 여러 대의 모니터를 가질 수는 없었습니다. 너무 리소스 집약적 인 지 알아보기 위해 테스트해야하지만 파일이 아닌 디렉토리를보고 있으면 저를 구할 수 있습니다. 버전 제어 된 트리를 모니터링하므로 관리 디렉토리 (예 : .svn 또는 .git)를 무시할 수있는 유연성을 제공합니다. – detly

+0

삭제 된 디렉토리의 모니터를 수동으로 취소하고 제거해야하는지 여부를 확인해야합니다. – detly

+0

무시 파일을 만들고 무시 파일의 파일 이름과 비교하여 파일 이름을 확인할 수도 있습니다. 가장 간단한 방법은 한 줄에 하나씩 파일을 작성하는 것이며,'f.seek (0)','ignorelist = f.readlines()','ignorelist : # skip '이 변경 될 때마다 –

2

"재귀 그것을 을 할 수있는 간단한 방법이 있을까요?"

저는 이것을 달성하기위한 "쉬운 방법"을 알지 못합니다. 리눅스에서의 inotify 나 BSD에서의 kqueue와 같은 기본 시스템은 재귀 적 시계를 자동으로 추가하는 기능을 제공하지 않습니다. 나는 또한 GIO 꼭대기에서 원하는 것을 레이어링하는 라이브러리를 전혀 모르고 있습니다.

따라서 직접 작성해야합니다. 일부 모서리의 경우 (예 : mkdir -p foo/bar/baz) 약간의 트릭이 될 수 있으므로 pynotify가 auto_add 기능 (grep ~ pynotify source)을 구현하고 GIO로 이식하는 방법을 제안합니다. GIO 당신이 한 번에 두 개 이상의 모니터를 할 수있는 경우