1年多前就看过相关内容了,当时python还不太会用看不懂别人写的代码,最近闲着又翻出来看看顺便解读下pyinotify的代码
使用源自于
http://blog.daviesliu.net/2008/04/24/sync/
这里的代码有2个错误,一个是base多定义了一次,另外就是有几行缩进好像有点问题,需要自己控制下缩进
一行一行解读
flags = IN_CLOSE_WRITE|IN_CREATE|IN_Q_OVERFLOW
这里flags的值是int行的,这里原来我半天没看懂。
如果写成
flags = pyinotify.IN_DELETE | pyinotify.IN_CREATE就好懂多了,这里用几个监控的类型的int值进行逻辑运算成监控需要监控的改变类型的数值具体数值怎么定义可以看看pyinotify.py文件中的class EventsCodes:中定义FLAG_COLLECTIONS的数值
dirs = {}
定义一个空的字典
base = '/log/lighttpd/cache/images/icon/u241'
这里定义了需要监控的文件夹,注意上面连接代码里有个base,自然是原作者忘记注释了其中一个,我们改成/tmp来测试
class UpdateParentDir(ProcessEvent):这里之前看不懂,特别是下面的process_IN_CLOSE_WRITE(self, event):,都不知道event哪里来的因为以前学c么什么函数重载,类的重载。这里其实就是什么派生重载子类而已
我们先看在pyinotify.py里看ProcessEvent这个类,这个类继承自_ProcessEvent这个类...,于是先去瞅瞅_ProcessEvent这个类
_ProcessEvent这个类没有init方法,只有__call__方法,call方法相当于重载了(),具体我们可以测试,我们先call方法里加入print "++++++++++++"
到最后我们再看结果,先跳过
继续看ProcessEvent类的init方法
def __init__(self, pevent=None, **kargs):
self.pevent = pevent
self.my_init(**kargs)
这个init方法也很简单,不赋值也没有问题self.my_init(**kargs)是留给我们自己写方法扩展的,可以不理会。所以这个init方法也没什么好看鸟。
我们可以直接看别人重载的方法在源代码pyinotify.py中的样子
def process_IN_Q_OVERFLOW(self, event):
log.warning('Event queue overflowed.')
def process_default(self, event):
pass
非常明了,不重载之前,原函数只是把对应变化写入log中,重载之后我们可以根据变化做自己想要的操作,比如备份改变的文件,或做同步操作之类。
现在重点是那个event,init里有说明type event: Event instance,不过UpdateParentDir还没开始调用,所以我们先放下Event模块不看。
先看下面的wm = WatchManager()
class WatchManager:
def __init__(self, exclude_filter=lambda path: False):
self._fd = self._inotify_wrapper.inotify_init()
init里主要看self._fd
这个fd是返回inotify监控的节点滴,这里调用了c封装的_inotify_wrapper,应该是初始化监控对象
WatchManager在监控代码中也没传参数,看到后面代码这个类还是通过类的add_watch方法传入内容的,看add_watch方法
def add_watch(self, path, mask, proc_fun=None, rec=False,
auto_add=False, do_glob=False, quiet=True,
exclude_filter=None):
这个方法主要是把path(也是就代码中的base指定的目录)格式化后传入,然后返回个path中内容的字典,监控工作还是没开始。
wd = ret_[rpath] = self.__add_watch(rpath, mask,
proc_fun,
auto_add,
exclude_filter)
add_watch里还调用了__add_watch,__add_watch里面又调用了watch方法,这里主要是从_inotify_wrapper这个c封装中获得inotify的对象
现在可以看把WatchManager和ProcessEvent联系起来的Notifier类了
class Notifier:
def __init__(self, watch_manager, default_proc_fun=None, read_freq=0,
threshold=0, timeout=None):
"""
@type watch_manager: WatchManager instance
@param default_proc_fun: Default processing method. If None, a new
instance of PrintAllEvents will be assigned.
@type default_proc_fun: instance of ProcessEvent
"""
# Watch Manager instance
self._watch_manager = watch_manager
# File descriptor
self._fd = self._watch_manager.get_fd()
# Poll object and registration
self._pollobj = select.poll()
self._pollobj.register(self._fd, select.POLLIN)