代码之家  ›  专栏  ›  技术社区  ›  detly FBruynbroeck

PyGTK/GIO:递归地监视目录中的更改

  •  4
  • detly FBruynbroeck  · 技术社区  · 14 年前

    获取以下演示代码(来自 GIO answer 对于这个问题),它使用了GIO FileMonitor 要监视目录的更改,请执行以下操作:

    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()
    

    运行此代码后,我可以创建和修改子节点,并收到更改通知。但是,这只适用于直系子女(我知道文档中没有其他说明)。以下最后一个shell命令不会产生通知:

    touch one
    mkdir two
    touch two/three
    

    有没有一个简单的方法让它递归?我不希望手动编写一些代码来查找目录创建并添加监视器、在删除时删除它们等等。

    我知道 pyinotify ,但我正在避免它,以便在非Linux内核(如FreeBSD或。。。其他人。据我所知,GIO FileMonitor在可用的地方在下面使用inotify,我可以理解不强调实现以保持某种程度的抽象,但它向我建议这应该是可能的。

    (为了以防万一,我最初把这个贴在了 PyGTK mailing list .)

    2 回复  |  直到 7 年前
        1
  •  1
  •   Wayne Werner    14 年前

    我不确定GIO是否允许您同时拥有多个显示器,但如果允许,您没有理由不能这样做:

    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我真的不能说。在Python中使用一些命令也完全可以实现自己的功能( 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()
    
        2
  •  2
  •   earl    14 年前

    “递归?”

    所以你很可能要自己建造这个。因为这在某些情况下可能有点诡计(例如。 mkdir -p foo/bar/baz )我建议看看pynotify是如何实现其 auto_add 功能(grep通过 pynotify source )把它传给吉奥。