python watchdog:監控文件系統事件的Python庫和shell工具

     watchdog用來監控指定目錄/文件的變化,如添加刪除文件或目錄、修改文件內容、重命名文件或目錄等,每種變化都會產生一個事件,且有一個特定的事件類與之對應,然後再通過事件處理類來處理對應的事件,怎麼樣處理事件完全可以自定義,只需繼承事件處理類的基類並重寫對應實例方法。

    先給一個官網的例子:

  1. import sys

  2. import time

  3. import logging

  4. from watchdog.observers import Observer

  5. from watchdog.events import LoggingEventHandler

  6.  
  7. if __name__ == "__main__":

  8. logging.basicConfig(level=logging.INFO,

  9. format='%(asctime)s - %(message)s',

  10. datefmt='%Y-%m-%d %H:%M:%S')

  11. path = sys.argv[1] if len(sys.argv) > 1 else '.'

  12. event_handler = LoggingEventHandler()

  13. observer = Observer()

  14. observer.schedule(event_handler, path, recursive=True)

  15. observer.start()

  16. try:

  17. while True:

  18. time.sleep(1)

  19. except KeyboardInterrupt:

  20. observer.stop()

  21. observer.join()

    使用LoggingEventHandler()事件處理器,當指定目錄發生任何變化都會打印消息到終端。

事件類(event):

  1. watchdog.events.FileSystemEvent(event_type,

  2. src_path,

  3. is_directory=False)

事件類基類,所有具體事件類的父類。當一個目錄或文件變化時,就會產生一個特定事件,也就是該類的子類。

屬性和方法:
event.is_directory
該事件是否由一個目錄觸發

event.src_path
觸發該事件的文件或目錄路徑

event.event_type
事件類型,爲moveddeletedcreatedmodified的其中之一

event.key
返回元組(event_type, src_path, is_directory)

watchdog.events.FileSystemEvent類的子類:

watchdog.events.FileDeletedEvent() 
文件被刪除時觸發該事件

watchdog.events.DirDeletedEvent() 
目錄被刪除時觸發該事件

watchdog.events.FileCreatedEvent() 
文件被創建時觸發該事件

watchdog.events.DirCreatedEvent() 
目錄被創建時觸發該事件

watchdog.events.FileModifiedEvent() 
文件被修改時觸發該事件(修改文件內容、修改文件inode信息如權限和訪問時間,都會觸發該事件)

watchdog.events.DirModifiedEvent() 
目錄被修改時觸發該事件

watchdog.events.FileMovedEvent() 
文件被移動或重命名時觸發該事件,因爲涉及文件移動,所以除了event.src_path表示原路徑,還有event.dest_path表示目的路徑

watchdog.events.DirMovedEvent() 
目錄被移動或重命名時觸發該事件,因爲涉及文件移動,所以除了event.src_path表示原路徑,還有event.dest_path表示目的路徑

事件處理類(event handler):

watchdog.events.FileSystemEventHandler()          

事件處理器的基類,用於處理事件,用戶需繼承該類,並在子類中重寫對應方法。

類實例方法如下:
self.dispatch(event)
接收到一個事件後,通過該方法來決定該event由下面哪個方法處理

self.on_any_event(event)
任何事件發生都會首先執行該方法,該方法默認爲空,dispatch()方法會先執行該方法,然後再把event分派給其他方法處理

self.on_moved(event)
Called when a file or a directory is moved or renamed,也就是處理DirMovedEventFileMovedEvent事件,子類需重寫該方法

self.on_created(event)
Called when a file or directory is created,也就是處理DirCreatedEventFileCreatedEvent事件,子類需重寫該方法

self.on_deleted(event)
Called when a file or directory is deleted,也就是處理DirDeletedEventFileDeletedEvent事件,子類需重寫該方法

self.on_modified(event)
Called when a file or directory is modified,也就是處理DirModifiedEventFileModifiedEvent事件,子類需重寫該方法

watchdog默認提供的一些事件處理類

  1. watchdog.events.PatternMatchingEventHandler(patterns=None,

  2. ignore_patterns=None,

  3. ignore_directories=False,

  4. case_sensitive=False)

該類會檢查觸發事件的src_pathdest_path(如 果有的話),是否與patterns指定的模式匹配;ignore_patterns是需要排除不處理的模式,如果路徑匹配該模式則不處理;還有 ignore_directories爲True則表示不處理由目錄引起的事件;case_sensitive爲True則表示路徑不區分大小寫。如果需 要按模式匹配處理事件,則可以繼承該類,不過需要自己實現on_moved()on_created()on_deleted()on_modified()這四個方法。

  1. watchdog.events.RegexMatchingEventHandler(regexes=[r".*"],

  2. ignore_regexes=[],

  3. ignore_directories=False,

  4. case_sensitive=False)

基本等同於PatternMatchingEventHandler()類,除了是使用正則,而不是模式匹配。

watchdog.events.LoggingEventHandler()               

使用logging模塊記錄所有事件信息,見文章開頭的列舉的官網例子。

例子:自定義事件處理類

  1. import time

  2. from watchdog.observers import Observer

  3. from watchdog.events import FileSystemEventHandler

  4.  
  5. class MyHandler(FileSystemEventHandler):

  6. def on_modified(self, event):

  7. if event.src_path == "/home/sapser/scripts/test.log": #監控指定文件內容、權限等變化

  8. print "log file %s changed!" % event.src_path

  9.  
  10. if __name__ == "__main__":

  11. event_handler = MyHandler()

  12. observer = Observer()

  13. observer.schedule(event_handler, path='.', recursive=False)

  14. observer.start()

  15. try:

  16. while True:

  17. time.sleep(1)

  18. except KeyboardInterrupt:

  19. observer.stop()

  20. observer.join()<span style="font-weight: 700;">

  21. </span>

observer:

watchdog.observers.Observer(timeout=1)         

該類實現了監控文件變化,觸發對應的事件類,然後調用關聯的事件處理類來處理事件。該類其實是threading.Thread的子類,通過observer.start()使之運行在一個線程中,不會阻塞主進程運行,然後可以調用observer.stop()來停止該線程

實例屬性及方法:
observer.schedule(event_handler, path, recursive=False)
監控指定路徑path,該路徑觸發任何事件都會調用event_handler來處理,如果path是目錄,則recursive=True則會遞歸監控該目錄的所有變化。每一次調用schedule()對一個路徑進行監控處理就叫做一個watch,schedule()方法會返回這個watch,接着可以對這個watch做其他操作,如爲該watch增加多個event處理器等
注:內部由一個字典handlers來保存所有watch,watch的值是一個集合,包含對應此watch的所有event handler:


 
  1. handlers = {

  2. watch1: set(event_handler1, event_handler2),

  3. watch2: set(event_handler),

  4. }

observer.add_handler_for_watch(event_handler, watch)
添加一個新的事件處理器到watch中,watch是ObservedWatch()類或其子類的實例

observer.remove_handler_for_watch(event_handler, watch)
從watch中移除一個事件處理器

observer.unschedule(watch)
移除一個watch及這個watch上的所有事件處理器

observer.unschedule_all()
移除所有watch及關聯的事件處理器

observer.on_thread_stop()
等同於observer.unschedule_all()

observer.stop()
調用該方法來停止observer線程

例子:爲一個路徑添加多個事件處理器


 
  1. import time

  2. import logging

  3. from watchdog.observers import Observer

  4. from watchdog.events import FileSystemEventHandler, LoggingEventHandler

  5. from watchdog.observers.api import ObservedWatch

  6.  
  7. class MyHandler(FileSystemEventHandler):

  8. def on_modified(self, event):

  9. if event.src_path == "/home/sapser/scripts/test.log":

  10. print "log file %s changed!" % event.src_path

  11.  
  12. if __name__ == "__main__":

  13. event_handler1 = MyHandler()

  14. observer = Observer()

  15. watch = observer.schedule(event_handler1, path='.', recursive=True)

  16.  
  17. logging.basicConfig(level=logging.INFO,

  18. format='%(asctime)s - %(message)s',

  19. datefmt='%Y-%m-%d %H:%M:%S')

  20. event_handler2 = LoggingEventHandler()

  21. observer.add_handler_for_watch(event_handler2, watch) #爲watch新添加一個event handler

  22. observer.start()

  23. try:

  24. while True:

  25. time.sleep(1)

  26. except KeyboardInterrupt:

  27. observer.stop()

  28. observer.join()

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章