一日一技:不用轮询,基于事件监控文件变动

一日一技:不用轮询,基于事件监控文件变动

一日一技:不用轮询,基于事件监控文件变动

摄影:产品经理
跟产品经理去喝酒
我们经常会遇到监控文件变化的需求。例如日志监控程序监控日志文件,一旦日志文件发生变化,就进行读取。或者是大批量爬虫的规则配置文件监控,爬虫本身持续运行,一旦规则文件发生修改就自动读取新的规则。
常见的做法,如果文件比较小,可以直接读取以后跟上次读取的内容做对比;也可以判断文件的修改时间是否发生变化;也可以判断文件的 md5值是否发生变化。
但不论哪种方案,都需要不停轮询检查文件。那有没有不轮询的方案呢?如果你的操作系统是 Linux,那么你可以使用 inotify 或者 asyncinotify。其中前者代码是同步模式,后者基于 asyncio 实现异步模式。他们都会在文件发生变动的时候,主动通过一个事件通知你,从而避免轮询。我们以 inotify 为例。
首先使用 pip 安装它:


python3 -m pip install inotify

然后,我们在当前目录创建一个文件:test.txt,一开始这个文件为空。
然后写一段代码:

from inotify.adapters import Inotify
import inotify.constants as Mask

inotify = Inotify()

inotify.add_watch('test.txt', mask=Mask.IN_MODIFY)
for event in inotify.event_gen(yield_nones=False):
    print(event)

运行效果如下图所示:
一日一技:不用轮询,基于事件监控文件变动
我们也可以同时监控多个文件:
i```
notify.add_watch('test.txt', mask=Mask.IN_MODIFY)
inotify.add_watch('test2.txt', mask=Mask.IN_MODIFY)
inotify.add_watch('test3.txt', mask=Mask.IN_MODIFY)

运行效果如下图所示:
![](http://www.icode9.com/i/li/?n=4&i=images/blog/202012/02/92647a5e7ef2e0920dbb3f4c8cdca14b.png?,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
除了监控文件修改,我们还可以监控文件被访问、打开、关闭、移动事件事件,他们分别对应:
* 文件被访问:Mask.IN_ACCESS
* 文件被修改:Mask.IN_MODIFY
* 文件被打开:Mask.IN_OPEN
* 文件被关闭并有写入:Mask.IN_CLOSE_WRITE
* 文件被关闭但是无写入:Mask.IN_CLOSE_NOWRITE
* 文件被删除:Mask.IN_DELETE
* 这些变化,我们可以通过|竖线来同时使用,例如:

inotify.add_watch('test.txt', mask=Mask.IN_MODIFY | Mask.IN_OPEN) # 文件被打开或者被修改,就发出事件



运行效果如下图所示:
![](http://www.icode9.com/i/li/?n=4&i=images/blog/202012/02/14d1aaa2d276a675e0c98700ad58d79d.png?,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
可以看到,因为要修改或者读取文件的时候,必定会打开文件,所以当我们直接使用cat test1.txt的时候,依然会看到IN_OPEN这个事件发生。
如果想进一步了解inotify,可以访问inotify 的 Github[1]。
asyncinotify 的用法与 inotify 几乎一样,可以参考asyncinotify 的官方文档[2]。
参考资料

[1]
inotify 的 Github: https://github.com/dsoprea/PyInotify
[2]
asyncinotify 的官方文档: https://asyncinotify.readthedocs.io/en/latest/
![](http://www.icode9.com/i/li/?n=4&i=images/blog/202012/02/5ad8bdfba1981908ad259b664d6a949c.png?,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
上一篇:方法


下一篇:Mysql 约束