问题
I want to monitor a dir , and the dir has sub dirs and in subdir there are somes files with .md
. (maybe there are some other files, such as *.swp...)
I only want to monitor the .md files, I have read the doc, and there is only a ExcludeFilter
, and in the issue : https://github.com/seb-m/pyinotify/issues/31 says, only dir can be filter but not files.
Now what I do is to filter in process_*
functions to check the event.name
by fnmatch
.
So if I only want to monitor the specified suffix files, is there a better way? Thanks.
This is the main code I have written:
!/usr/bin/env python
# -*- coding: utf-8 -*-
import pyinotify
import fnmatch
def suffix_filter(fn):
suffixes = ["*.md", "*.markdown"]
for suffix in suffixes:
if fnmatch.fnmatch(fn, suffix):
return False
return True
class EventHandler(pyinotify.ProcessEvent):
def process_IN_CREATE(self, event):
if not suffix_filter(event.name):
print "Creating:", event.pathname
def process_IN_DELETE(self, event):
if not suffix_filter(event.name):
print "Removing:", event.pathname
def process_IN_MODIFY(self, event):
if not suffix_filter(event.name):
print "Modifing:", event.pathname
def process_default(self, event):
print "Default:", event.pathname
回答1:
I think you basically have the right idea, but that it could be implemented more easily.
The ProcessEvent
class in the pyinotify module already has a hook you can use to filter the processing of events. It's specified via an optional pevent
keyword argument given on the call to the constructor and is saved in the instance's self.pevent
attribute. The default value is None
. It's value is used in the class' __call__()
method as shown in the following snippet from the pyinotify.py
source file:
def __call__(self, event):
stop_chaining = False
if self.pevent is not None:
# By default methods return None so we set as guideline
# that methods asking for stop chaining must explicitly
# return non None or non False values, otherwise the default
# behavior will be to accept chain call to the corresponding
# local method.
stop_chaining = self.pevent(event)
if not stop_chaining:
return _ProcessEvent.__call__(self, event)
So you could use it only allow events for files with certain suffixes (aka extensions) with something like this:
SUFFIXES = {".md", ".markdown"}
def suffix_filter(event):
# return True to stop processing of event (to "stop chaining")
return os.path.splitext(event.name)[1] not in SUFFIXES
processevent = ProcessEvent(pevent=suffix_filter)
回答2:
There's nothing particularly wrong with your solution, but you want your inotify handler to be as fast as possible, so there are a few optimizations you can make.
You should move your match suffixes out of your function, so the compiler only builds them once:
EXTS = set([".md", ".markdown"])
I made them a set so you can do a more efficient match:
def suffix_filter(fn):
ext = os.path.splitext(fn)[1]
if ext in EXTS:
return False
return True
I'm only presuming that os.path.splitext
and a set search are faster than an iterative fnmatch
, but this may not be true for your really small list of extensions - you should test it.
(Note: I've mirrored your code above where you return False when you make a match, but I'm not convinced that's what you want - it is at the very least not very clear to someone reading your code)
回答3:
You can use the __call__
method of ProcessEvent
to centralize the call to suffix_filter
:
class EventHandler(pyinotify.ProcessEvent):
def __call__(self, event):
if not suffix_filter(event.name):
super(EventHandler, self).__call__(event)
def process_IN_CREATE(self, event):
print "Creating:", event.pathname
def process_IN_DELETE(self, event):
print "Removing:", event.pathname
def process_IN_MODIFY(self, event):
print "Modifying:", event.pathname
来源:https://stackoverflow.com/questions/18305026/python-pyinotify-to-monitor-the-specified-suffix-files-in-a-dir