使用以下演示代码(从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
有一种简单的方法可以使其递归吗?我宁愿不手动编写寻找目录创建的东西并添加监视器,删除时删除它们等等。
预期用途是用于VCS文件浏览器扩展,以便能够在工作副本中缓存文件的状态,并在更改时单独更新它们。因此,可能会有数十到数千个(或更多)目录需要监视。我想找到工作副本的根目录并在那里添加文件监视器。
我知道pyinotify,但我正在避免它,以便在非Linux内核(如FreeBSD或其他人)下运行。据我所知,GIO FileMonitor在可用的地方使用inotify,我可以理解不强调实现以保持某种程度的抽象,但它告诉我它应该是可能的。
(如果重要,我最初在PyGTK mailing list上发布了这个。)
答案 0 :(得分:2)
“有一种简单的方法可以做到这一点 递归?“
我不知道实现这一目标的任何“简单方法”。底层系统,例如Linux上的inotify或BSD上的kqueue,不提供自动添加递归手表的工具。我也不知道你在GIO上面想要什么库。
所以你很可能必须自己构建它。因为在某些极端情况下这可能有点戏法(例如mkdir -p foo/bar/baz
)我建议看看pynotify如何实现其auto_add
功能(grep通过pynotify source)并将其移植到GIO
答案 1 :(得分:1)
我不确定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的知识几乎为零,我真的无法说出来。使用一些命令(os.listdir
等)完全可以在Python中滚动自己。它可能看起来像这样
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()