python基于watchdog庫(kù)實(shí)現(xiàn)文件系統(tǒng)監(jiān)控
Watchdog庫(kù)是Python中一個(gè)用于監(jiān)控文件系統(tǒng)變化的第三方庫(kù)。它能夠?qū)崟r(shí)監(jiān)測(cè)文件或目錄的創(chuàng)建、修改、刪除等操作,并在這些事件發(fā)生時(shí)觸發(fā)相應(yīng)的處理邏輯,因此也被稱(chēng)為文件看門(mén)狗。
Watchdog庫(kù)的官方倉(cāng)庫(kù)見(jiàn):watchdog,Watchdog庫(kù)的官方文檔見(jiàn):watchdog-doc。Watchdog庫(kù)的安裝命令如下:
python -m pip install -U watchdog
注意:Watchdog庫(kù)最新版本(2.1.5以上版本)需在Python3.9以上版本運(yùn)行。若使用Python3.4或3.5,應(yīng)選用Watchdog版本低于1.0.0;若使用Python3.6至3.8,應(yīng)選用Watchdog版本低于2.0.0。
1 使用示例
基礎(chǔ)示例
以下示例程序?qū)⒁赃f歸方式監(jiān)控指定目錄及其子文件夾中文件系統(tǒng)的變化情況,包括文件或文件夾的創(chuàng)建、修改、移動(dòng)、刪除,并將這些變化記錄到控制臺(tái)中:
import sys
# 導(dǎo)入logging模塊,用于記錄程序運(yùn)行時(shí)的日志信息
import logging
# 從watchdog.observers模塊中導(dǎo)入Observer類(lèi),用于監(jiān)控文件系統(tǒng)的變化
from watchdog.observers import Observer
# 從watchdog.events模塊中導(dǎo)入LoggingEventHandler類(lèi),用于處理文件系統(tǒng)事件并記錄日志
from watchdog.events import LoggingEventHandler
if __name__ == "__main__":
# 配置日志記錄的基本設(shè)置
# level=logging.INFO表示只記錄INFO級(jí)別及以上的日志信息
# format='%(asctime)s - %(message)s'指定日志的輸出格式,包含時(shí)間戳和日志消息
# datefmt='%Y-%m-%d %H:%M:%S'指定時(shí)間戳的格式
logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
# 指定要監(jiān)控的文件夾路徑,該文件夾必須存在
path = "demo_folder"
# 創(chuàng)建一個(gè)LoggingEventHandler對(duì)象,用于處理文件系統(tǒng)事件并記錄日志
event_handler = LoggingEventHandler()
# 創(chuàng)建一個(gè)Observer對(duì)象,用于監(jiān)控文件系統(tǒng)的變化
observer = Observer()
# 安排觀察者監(jiān)控指定路徑下的文件系統(tǒng)事件
# event_handler是事件處理程序
# path是要監(jiān)控的路徑
# recursive=True表示遞歸監(jiān)控該路徑下的所有子文件夾
observer.schedule(event_handler, path, recursive=True)
# 啟動(dòng)觀察者,開(kāi)始監(jiān)控文件系統(tǒng)的變化
observer.start()
try:
# 當(dāng)觀察者處于活動(dòng)狀態(tài)時(shí),持續(xù)循環(huán)
while observer.is_alive():
# 等待1秒,讓觀察者有時(shí)間處理文件系統(tǒng)事件
observer.join(1)
finally:
# 停止觀察者,結(jié)束文件系統(tǒng)的監(jiān)控
observer.stop()
# 等待觀察者線程結(jié)束
observer.join()
Watchdog事件類(lèi)介紹
Watchdog庫(kù)提供了一系列事件類(lèi),用于監(jiān)控文件系統(tǒng)的各種變化,這些變化包括:
- 創(chuàng)建事件
on_create:涵蓋文件和文件夾的創(chuàng)建情況,當(dāng)有新的文件或者文件夾在監(jiān)控路徑下生成時(shí)觸發(fā)相應(yīng)事件。 - 刪除事件
on_delete:當(dāng)文件或者文件夾被從監(jiān)控路徑中移除時(shí)觸發(fā),分別有針對(duì)文件和文件夾的不同事件類(lèi)。 - 修改事件
on_modified:文件夾內(nèi)新增、刪除文件或子文件夾等內(nèi)容變化時(shí)觸發(fā)文件夾修改事件。 - 移動(dòng) / 重命名事件
on_moved:文件或文件夾的位置發(fā)生移動(dòng),或者名稱(chēng)被更改時(shí)觸發(fā)相應(yīng)事件,該事件會(huì)記錄原路徑和新路徑。
基于這些變化Watchdog庫(kù)中存在8個(gè)事件類(lèi):
| 事件類(lèi)名 | 觸發(fā)場(chǎng)景 |
|---|---|
FileCreatedEvent | 新文件被創(chuàng)建時(shí)觸發(fā) |
DirCreatedEvent | 新文件夾被創(chuàng)建時(shí)觸發(fā) |
FileDeletedEvent | 文件被刪除時(shí)觸發(fā) |
DirDeletedEvent | 文件夾被刪除時(shí)觸發(fā) |
FileModifiedEvent | 文件內(nèi)容被修改時(shí)觸發(fā) |
DirModifiedEvent | 文件夾內(nèi)容(如添加、刪除子文件或子文件夾)發(fā)生變化時(shí)觸發(fā) |
FileMovedEvent | 文件被移動(dòng)或重命名時(shí)觸發(fā) |
DirMovedEvent | 文件夾被移動(dòng)或重命名時(shí)觸發(fā) |
注意:在某些情形下,多個(gè)Watchdog事件可能會(huì)一同觸發(fā),這往往和文件系統(tǒng)操作的特性以及Watchdog對(duì)這些操作的響應(yīng)機(jī)制有關(guān)。例如,當(dāng)移動(dòng)一個(gè)文件時(shí),會(huì)同時(shí)觸發(fā)FileMovedEvent(文件移動(dòng)事件)和FileDeletedEvent(文件刪除事件),因?yàn)橐苿?dòng)文件的操作在源路徑上相當(dāng)于刪除文件,同時(shí)在目標(biāo)路徑上會(huì)觸發(fā)FileCreatedEvent(文件創(chuàng)建事件)。
以下代碼的主要功能是監(jiān)控指定目錄下文件系統(tǒng)的各種事件,如文件或目錄的創(chuàng)建、刪除、移動(dòng)和修改,并對(duì)這些事件進(jìn)行重寫(xiě)和相應(yīng)的處理:
# 該類(lèi)用于處理文件系統(tǒng)事件,如文件的創(chuàng)建、刪除、修改等
from watchdog.events import FileSystemEventHandler
from watchdog.observers import Observer
# 定義一個(gè)自定義的文件事件處理類(lèi),繼承自FileSystemEventHandler
class FileEventHandler(FileSystemEventHandler):
def __init__(self):
FileSystemEventHandler.__init__(self)
# 初始化一個(gè)空列表,用于存儲(chǔ)文件名
self.file_names = []
# 當(dāng)文件或目錄被移動(dòng)時(shí)觸發(fā)此方法
def on_moved(self, event):
# 判斷是否是目錄移動(dòng)
if event.is_directory:
# 打印目錄移動(dòng)的信息
print(f"目錄從 {event.src_path} 移動(dòng)到 {event.dest_path}")
else:
# 打印文件移動(dòng)的信息
print(f"文件從 {event.src_path} 移動(dòng)到 {event.dest_path}")
# 當(dāng)文件或目錄被創(chuàng)建時(shí)觸發(fā)此方法
def on_created(self, event):
# 判斷是否是目錄創(chuàng)建
if event.is_directory:
# 打印目錄創(chuàng)建的信息
print(f"目錄已創(chuàng)建: {event.src_path}")
else:
# 打印文件創(chuàng)建的信息
print(f"文件已創(chuàng)建: {event.src_path}")
# 從文件的完整路徑中提取文件名
file_full_name = str(event.src_path.split('/')[-1])
if file_full_name.endswith('.csv'):
# 如果是csv文件,將其添加到文件名列表中
self.file_names.append(file_full_name)
# 打印文件名列表
print(self.file_names)
# 當(dāng)文件或目錄被刪除時(shí)觸發(fā)此方法
def on_deleted(self, event):
# 判斷是否是目錄刪除
if event.is_directory:
# 打印目錄刪除的信息
print(f"目錄已刪除: {event.src_path}")
else:
# 打印文件刪除的信息
print(f"文件已刪除: {event.src_path}")
# 當(dāng)文件或目錄被修改時(shí)觸發(fā)此方法,注釋代碼表示不觸發(fā)修改事件
# def on_modified(self, event):
# pass
if __name__ == "__main__":
# 創(chuàng)建一個(gè)Observer對(duì)象,用于監(jiān)控文件系統(tǒng)的變化
observer = Observer()
# 創(chuàng)建一個(gè)自定義的文件事件處理對(duì)象
event_handler = FileEventHandler()
# 定義要監(jiān)控的目錄
watch_directory = "demo_folder"
# 將事件處理對(duì)象和要監(jiān)控的目錄添加到觀察者中,并設(shè)置為遞歸監(jiān)控
observer.schedule(event_handler, watch_directory, recursive=True)
# 啟動(dòng)觀察者,開(kāi)始監(jiān)控文件系統(tǒng)的變化
observer.start()
try:
# 當(dāng)觀察者處于活動(dòng)狀態(tài)時(shí),持續(xù)循環(huán)
while observer.is_alive():
# 等待1秒,讓觀察者有時(shí)間處理文件系統(tǒng)事件
observer.join(1)
finally:
# 停止觀察者,結(jié)束文件系統(tǒng)的監(jiān)控
observer.stop()
# 等待觀察者線程結(jié)束
observer.join()
2.快照功能
采用基于定時(shí)器的批處理策略,合并并延遲頻繁的文件變更事件,能夠有效降低系統(tǒng)負(fù)載。具體做法是:當(dāng)系統(tǒng)檢測(cè)到文件首次變動(dòng)時(shí),啟動(dòng)可重置的計(jì)時(shí)器,在設(shè)定的延遲期內(nèi)累積后續(xù)變更事件,待計(jì)時(shí)器超時(shí)后,再統(tǒng)一通過(guò)對(duì)比當(dāng)前文件系統(tǒng)狀態(tài)與上次緩存快照,可精準(zhǔn)識(shí)別所有變更項(xiàng)。具體實(shí)現(xiàn)代碼如下:
import time
import os
import threading
from watchdog.observers import Observer
from watchdog.events import *
from watchdog.utils.dirsnapshot import DirectorySnapshot, DirectorySnapshotDiff
class FileChangeHandler(FileSystemEventHandler):
def __init__(self, monitored_path, delay=0.5):
# 調(diào)用父類(lèi)構(gòu)造函數(shù)
super().__init__()
# 被監(jiān)控的目錄路徑
self.monitored_path = monitored_path
self.delay = delay
# 定時(shí)器對(duì)象,用于延遲檢查
self.delay_timer = None
# 快照用于記錄指定目錄在某個(gè)時(shí)間點(diǎn)的狀態(tài),包含了目錄下所有文件和子目錄的信息,
# 記錄目錄的初始快照
self.initial_snapshot = DirectorySnapshot(self.monitored_path)
def on_any_event(self, event):
# 通過(guò)定時(shí)器減少不必要的檢查
# 如果定時(shí)器已存在,取消它
if self.delay_timer:
self.delay_timer.cancel()
# 創(chuàng)建一個(gè)新的定時(shí)器,延遲后執(zhí)行檢查快照的操作
# 通過(guò)快照檢測(cè)文件系統(tǒng)變化
self.delay_timer = threading.Timer(self.delay, self._check_directory_changes)
self.delay_timer.start()
def _check_directory_changes(self):
# 獲取當(dāng)前目錄的新快照
new_snapshot = DirectorySnapshot(self.monitored_path)
# 計(jì)算新舊快照之間的差異
snapshot_difference = DirectorySnapshotDiff(self.initial_snapshot, new_snapshot)
# 更新初始快照為新快照
self.initial_snapshot = new_snapshot
# 清空定時(shí)器
self.delay_timer = None
# 打印目錄變化信息
self._print_changes(snapshot_difference)
def _print_changes(self, diff):
# 打印文件和目錄的創(chuàng)建、刪除、修改和移動(dòng)信息
print("創(chuàng)建的文件:", diff.files_created)
print("刪除的文件:", diff.files_deleted)
print("修改的文件:", diff.files_modified)
print("移動(dòng)的文件:", diff.files_moved)
print("修改的目錄:", diff.dirs_modified)
print("移動(dòng)的目錄:", diff.dirs_moved)
print("刪除的目錄:", diff.dirs_deleted)
print("創(chuàng)建的目錄:", diff.dirs_created)
class DirectoryMonitor:
def __init__(self, monitored_path):
# 被監(jiān)控的目錄路徑
self.monitored_path = monitored_path
# 創(chuàng)建一個(gè)觀察者對(duì)象
self.directory_observer = Observer()
def start_monitoring(self):
# 創(chuàng)建文件變化處理對(duì)象
change_handler = FileChangeHandler(self.monitored_path)
# 安排觀察者監(jiān)控指定目錄,遞歸地監(jiān)控子目錄
self.directory_observer.schedule(change_handler, self.monitored_path, recursive=True)
# 啟動(dòng)觀察者
self.directory_observer.start()
def stop_monitoring(self):
# 停止觀察者
self.directory_observer.stop()
# 等待觀察者線程結(jié)束
self.directory_observer.join()
if __name__ == "__main__":
monitor = DirectoryMonitor("demo_folder")
# 開(kāi)始監(jiān)控
monitor.start_monitoring()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
monitor.stop_monitoring()
3.多文件夾監(jiān)控
以下代碼展示了通過(guò)schedule方法為每個(gè)目錄注冊(cè)事件處理程序,實(shí)現(xiàn)對(duì)多個(gè)目錄的同步監(jiān)控:
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
class CustomFileEventHandler(FileSystemEventHandler):
def on_created(self, event):
patterns = [“*.jpg”, “*.png”, “*.gif”] # 只監(jiān)控圖片文件 def on_modified(self, event): print(f“圖片文件有變化:{event.src_path}”)
entity = "directory" if event.is_directory else "file"
print(f"{entity} on_created: {event.src_path}")
if __name__ == "__main__":
file_observer = Observer()
monitored_directories = ['demo_folder', 'demo_folder2']
file_event_handler = CustomFileEventHandler()
for directory in monitored_directories:
# 為每個(gè)目錄注冊(cè)事件處理程序
file_observer.schedule(file_event_handler, directory, recursive=True)
file_observer.start()
try:
# 當(dāng)觀察者處于活動(dòng)狀態(tài)時(shí),持續(xù)循環(huán)
while file_observer.is_alive():
# 等待1秒,讓觀察者有時(shí)間處理文件系統(tǒng)事件
file_observer.join(1)
finally:
# 停止觀察者,結(jié)束文件系統(tǒng)的監(jiān)控
file_observer.stop()
# 等待觀察者線程結(jié)束
file_observer.join()到此這篇關(guān)于python基于watchdog庫(kù)實(shí)現(xiàn)文件系統(tǒng)監(jiān)控的文章就介紹到這了,更多相關(guān)python watchdog文件系統(tǒng)監(jiān)控內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python DataFrame轉(zhuǎn)dict字典過(guò)程詳解
這篇文章主要介紹了python DataFrame轉(zhuǎn)dict字典過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12
Python學(xué)習(xí)筆記基本數(shù)據(jù)結(jié)構(gòu)之序列類(lèi)型list tuple range用法分析
這篇文章主要介紹了Python學(xué)習(xí)筆記基本數(shù)據(jù)結(jié)構(gòu)之序列類(lèi)型list tuple range用法,結(jié)合具體實(shí)例形式分析了Python序列類(lèi)型list tuple range基本概念、定義與使用技巧,需要的朋友可以參考下2019-06-06
python實(shí)現(xiàn)照片集變成視頻的代碼實(shí)現(xiàn)
看著電腦里亂七八糟的照片,有大有小,寬高不一,突然想找個(gè)方式把他們統(tǒng)一起來(lái),然后做成視頻更好,所以本文給大家介紹了python實(shí)現(xiàn)照片集變成視頻的實(shí)現(xiàn),需要的朋友可以參考下2024-10-10
在PyCharm中高效使用遠(yuǎn)程文件編輯功能的實(shí)現(xiàn)
PyCharm作為業(yè)界領(lǐng)先的集成開(kāi)發(fā)環(huán)境(IDE),提供了強(qiáng)大的本地和遠(yuǎn)程開(kāi)發(fā)功能,本文詳細(xì)介紹了如何在PyCharm中使用遠(yuǎn)程文件編輯功能,希望能夠幫助你提高遠(yuǎn)程開(kāi)發(fā)的效率和體驗(yàn)2024-08-08
Python實(shí)現(xiàn)爬取馬云的微博功能示例
這篇文章主要介紹了Python實(shí)現(xiàn)爬取馬云的微博功能,結(jié)合實(shí)例形式較為詳細(xì)的分析了Python模擬ajax請(qǐng)求爬取馬云微博的相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下2019-02-02
解決python運(yùn)行啟動(dòng)報(bào)錯(cuò)問(wèn)題
這篇文章主要介紹了解決python運(yùn)行啟動(dòng)報(bào)錯(cuò)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-06-06

