你可能会问,为什么不用python的watchdog
?因为watchdog
用户可重写的实例方法就那么几个:
self.on_any_event(event)
# 任何事件发生都会首先执行该方法,该方法默认为空,dispatch()方法会先执行该方法,然后再把 event 分派给其他方法处理
self.on_moved(event)
# 处理 DirMovedEvent 和 FileMovedEvent 事件,默认为空
self.on_created(event)
# 处理 DirCreatedEvent 和 FileCreatedEvent 事件,默认为空
self.on_deleted(event)
# 处理 DirDeletedEvent 和 FileDeletedEvent 事件,默认为空
self.on_modified(event)
# 处理 DirModifiedEvent 和 FileModifiedEvent 事件,默认为空
它无法判断文件操作是否完成,你需要自己写其他逻辑来判断。关于watchdog
在CSDN有篇很详尽的博文–WatchDog 使用经验总结,以上事件也转自那篇博文。
下面我们来说说pyinotify,Pyinotify依赖于Linux内核的功能—inotify(内核2.6.13合并),它支持的事件如下:
@cvar IN_ACCESS: File was accessed.
@type IN_ACCESS: int
@cvar IN_MODIFY: File was modified.
@type IN_MODIFY: int
@cvar IN_ATTRIB: Metadata changed.
@type IN_ATTRIB: int
@cvar IN_CLOSE_WRITE: Writtable file was closed.
@type IN_CLOSE_WRITE: int
@cvar IN_CLOSE_NOWRITE: Unwrittable file closed.
@type IN_CLOSE_NOWRITE: int
@cvar IN_OPEN: File was opened.
@type IN_OPEN: int
@cvar IN_MOVED_FROM: File was moved from X.
@type IN_MOVED_FROM: int
@cvar IN_MOVED_TO: File was moved to Y.
@type IN_MOVED_TO: int
@cvar IN_CREATE: Subfile was created.
@type IN_CREATE: int
@cvar IN_DELETE: Subfile was deleted.
@type IN_DELETE: int
@cvar IN_DELETE_SELF: Self (watched item itself) was deleted.
@type IN_DELETE_SELF: int
@cvar IN_MOVE_SELF: Self (watched item itself) was moved.
@type IN_MOVE_SELF: int
@cvar IN_UNMOUNT: Backing fs was unmounted.
@type IN_UNMOUNT: int
@cvar IN_Q_OVERFLOW: Event queued overflowed.
@type IN_Q_OVERFLOW: int
@cvar IN_IGNORED: File was ignored.
@type IN_IGNORED: int
@cvar IN_ONLYDIR: only watch the path if it is a directory (new
in kernel 2.6.15).
@type IN_ONLYDIR: int
@cvar IN_DONT_FOLLOW: don't follow a symlink (new in kernel 2.6.15).
IN_ONLYDIR we can make sure that we don't watch
the target of symlinks.
@type IN_DONT_FOLLOW: int
@cvar IN_EXCL_UNLINK: Events are not generated for children after they
have been unlinked from the watched directory.
(new in kernel 2.6.36).
@type IN_EXCL_UNLINK: int
@cvar IN_MASK_ADD: add to the mask of an already existing watch (new
in kernel 2.6.14).
@type IN_MASK_ADD: int
@cvar IN_ISDIR: Event occurred against dir.
@type IN_ISDIR: int
@cvar IN_ONESHOT: Only send event once.
@type IN_ONESHOT: int
@cvar ALL_EVENTS: Alias for considering all of the events.
@type ALL_EVENTS: int
如果你需要监控一个文件夹,它定期有文件上传,上传完成后需要对最新的文件进行操作,那么使用pyinotify
的IN_CLOSE_WRITE
事件就非常合适。
使用pyinotify
的方法有如下几种:
- Using the Notifier class without timeout
The corresponding tutorial file can be found here: tutorial_notifier.py - Using the Notifier class with a timeout
- Using the ThreadedNotifier Class
The corresponding tutorial file can be found here: tutorial_threadednotifier.py. - Using the AsyncNotifier Class
The corresponding tutorial file can be found here: tutorial_asyncnotifier.py. - 由于python3.6之后,asyncore已经被asyncio 取代,所以有了这个诡异的官方例程:pyinotify/asyncio_notifier.py。里面完全没写各种事件怎么处理,文档也没有。
后来一番搜索,终于找到了这个Using pyinotify with python 3 asyncio,代码如下:
import pyinotify
import asyncio
class EventHandler(pyinotify.ProcessEvent):
def process_IN_CREATE(self, event):
if not event.dir:
print("Got new file: ", event.pathname)
print("Something changed in path: ", event.path)
print("The file changed: ", event.name)
wm = pyinotify.WatchManager() # Watch Manager
mask = pyinotify.IN_DELETE | pyinotify.IN_CREATE # watched events
loop = asyncio.get_event_loop()
notifier = pyinotify.AsyncioNotifier(wm, loop, default_proc_fun=EventHandler())
wdd = wm.add_watch('.', mask, rec=True, auto_add=True)
try:
loop.run_forever()
except:
print('\nshutting down...')
loop.stop()
notifier.stop()
参考文献: