本文介绍了PyGTK/GIO:递归监视目录的变化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

采用以下演示代码(来自 GIO 答案这个问题),它使用 GIO FileMonitor 来监视更改目录:

Take the following demo code (from the GIO answer to this question), which uses a GIO FileMonitor to monitor a directory for changes:

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 命令不会产生通知:

After running this code, I can then create and modify child nodes and be notified of the changes. However, this only works for immediate children (I am aware that the docs don't say otherwise). The last of the following shell commands will not result in a notification:

touch one
mkdir two
touch two/three

有没有简单的方法让它递归?我宁愿不手动编写查找目录创建和添加监视器、删除时删除它们等的代码.

Is there an easy way to make it recursive? I'd rather not manually code something that looks for directory creation and adds a monitor, removing them on deletion, etc.

预期用途是用于 VCS 文件浏览器扩展,以便能够缓存工作副本中文件的状态并在更改时单独更新它们.因此,可能有数十到数千(或更多)目录需要监控.我只想找到工作副本的根目录并在那里添加文件监视器.

The intended use is for a VCS file browser extension, to be able to cache the statuses of files in a working copy and update them individually on changes. So there might by anywhere from tens to thousands (or more) directories to monitor. I'd like to just find the root of the working copy and add the file monitor there.

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

I know about pyinotify, but I'm avoiding it so that this works under non-Linux kernels such as FreeBSD or... others. As far as I'm aware, the GIO FileMonitor uses inotify underneath where available, and I can understand not emphasising the implementation to maintain some degree of abstraction, but it suggested to me that it should be possible.

(以防万一,我最初将其发布在 PyGTK 邮件列表.)

(In case it matters, I originally posted this on the PyGTK mailing list.)

推荐答案

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

I'm not sure if GIO allows you to have more than one monitor at once, but if it does there's no* reason you can't do something like this:

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 中推出自己的命令.它可能看起来像这样

*when I say no reason, there's the possibility that this could become a resource hog, though with nearly zero knowledge about GIO I couldn't really say. It's also entirely possible to roll your own in Python with a few commands (os.listdir among others). It might look something like this

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

这篇关于PyGTK/GIO:递归监视目录的变化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-03 08:01