pyinotify asyncio監控文件和文件夾變化

你可能會問,爲什麼不用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

如果你需要監控一個文件夾,它定期有文件上傳,上傳完成後需要對最新的文件進行操作,那麼使用pyinotifyIN_CLOSE_WRITE事件就非常合適。
使用pyinotify的方法有如下幾種:

  1. Using the Notifier class without timeout
    The corresponding tutorial file can be found here: tutorial_notifier.py
  2. Using the Notifier class with a timeout
  3. Using the ThreadedNotifier Class
    The corresponding tutorial file can be found here: tutorial_threadednotifier.py.
  4. Using the AsyncNotifier Class
    The corresponding tutorial file can be found here: tutorial_asyncnotifier.py.
  5. 由於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()

參考文獻:

  1. python文件夾,文件監聽工具(pyinotify,watchdog)
  2. pyinotify
  3. Tutorial · seb-m/pyinotify Wiki
  4. Using pyinotify with python 3 asyncio
  5. WatchDog 使用經驗總結
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章