watchdog用來監控指定目錄/文件的變化,如添加刪除文件或目錄、修改文件內容、重命名文件或目錄等,每種變化都會產生一個事件,且有一個特定的事件類與之對應,然後再通過事件處理類來處理對應的事件,怎麼樣處理事件完全可以自定義,只需繼承事件處理類的基類並重寫對應實例方法。
先給一個官網的例子:
-
import sys
-
import time
-
import logging
-
from watchdog.observers import Observer
-
from watchdog.events import LoggingEventHandler
-
if __name__ == "__main__":
-
logging.basicConfig(level=logging.INFO,
-
format='%(asctime)s - %(message)s',
-
datefmt='%Y-%m-%d %H:%M:%S')
-
path = sys.argv[1] if len(sys.argv) > 1 else '.'
-
event_handler = LoggingEventHandler()
-
observer = Observer()
-
observer.schedule(event_handler, path, recursive=True)
-
observer.start()
-
try:
-
while True:
-
time.sleep(1)
-
except KeyboardInterrupt:
-
observer.stop()
-
observer.join()
使用LoggingEventHandler()
事件處理器,當指定目錄發生任何變化都會打印消息到終端。
事件類(event):
-
watchdog.events.FileSystemEvent(event_type,
-
src_path,
-
is_directory=False)
事件類基類,所有具體事件類的父類。當一個目錄或文件變化時,就會產生一個特定事件,也就是該類的子類。
屬性和方法:
event.is_directory
該事件是否由一個目錄觸發
event.src_path
觸發該事件的文件或目錄路徑
event.event_type
事件類型,爲moved
、deleted
、created
或modified
的其中之一
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,也就是處理DirMovedEvent
和FileMovedEvent
事件,子類需重寫該方法
self.on_created(event)
Called when a file or directory is created,也就是處理DirCreatedEvent
和FileCreatedEvent
事件,子類需重寫該方法
self.on_deleted(event)
Called when a file or directory is deleted,也就是處理DirDeletedEvent
和FileDeletedEvent
事件,子類需重寫該方法
self.on_modified(event)
Called when a file or directory is modified,也就是處理DirModifiedEvent
和FileModifiedEvent
事件,子類需重寫該方法
watchdog默認提供的一些事件處理類
-
watchdog.events.PatternMatchingEventHandler(patterns=None,
-
ignore_patterns=None,
-
ignore_directories=False,
-
case_sensitive=False)
該類會檢查觸發事件的src_path
和dest_path
(如 果有的話),是否與patterns指定的模式匹配;ignore_patterns是需要排除不處理的模式,如果路徑匹配該模式則不處理;還有 ignore_directories爲True則表示不處理由目錄引起的事件;case_sensitive爲True則表示路徑不區分大小寫。如果需 要按模式匹配處理事件,則可以繼承該類,不過需要自己實現on_moved()
、on_created()
、on_deleted()
、on_modified()
這四個方法。
-
watchdog.events.RegexMatchingEventHandler(regexes=[r".*"],
-
ignore_regexes=[],
-
ignore_directories=False,
-
case_sensitive=False)
基本等同於PatternMatchingEventHandler()類,除了是使用正則,而不是模式匹配。
watchdog.events.LoggingEventHandler()
使用logging模塊記錄所有事件信息,見文章開頭的列舉的官網例子。
例子:自定義事件處理類
-
import time
-
from watchdog.observers import Observer
-
from watchdog.events import FileSystemEventHandler
-
class MyHandler(FileSystemEventHandler):
-
def on_modified(self, event):
-
if event.src_path == "/home/sapser/scripts/test.log": #監控指定文件內容、權限等變化
-
print "log file %s changed!" % event.src_path
-
if __name__ == "__main__":
-
event_handler = MyHandler()
-
observer = Observer()
-
observer.schedule(event_handler, path='.', recursive=False)
-
observer.start()
-
try:
-
while True:
-
time.sleep(1)
-
except KeyboardInterrupt:
-
observer.stop()
-
observer.join()<span style="font-weight: 700;">
-
</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:
-
handlers = {
-
watch1: set(event_handler1, event_handler2),
-
watch2: set(event_handler),
-
}
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線程
例子:爲一個路徑添加多個事件處理器
-
import time
-
import logging
-
from watchdog.observers import Observer
-
from watchdog.events import FileSystemEventHandler, LoggingEventHandler
-
from watchdog.observers.api import ObservedWatch
-
class MyHandler(FileSystemEventHandler):
-
def on_modified(self, event):
-
if event.src_path == "/home/sapser/scripts/test.log":
-
print "log file %s changed!" % event.src_path
-
if __name__ == "__main__":
-
event_handler1 = MyHandler()
-
observer = Observer()
-
watch = observer.schedule(event_handler1, path='.', recursive=True)
-
logging.basicConfig(level=logging.INFO,
-
format='%(asctime)s - %(message)s',
-
datefmt='%Y-%m-%d %H:%M:%S')
-
event_handler2 = LoggingEventHandler()
-
observer.add_handler_for_watch(event_handler2, watch) #爲watch新添加一個event handler
-
observer.start()
-
try:
-
while True:
-
time.sleep(1)
-
except KeyboardInterrupt:
-
observer.stop()
-
observer.join()