轻松监控文件系统变化:Watchdog | python小知识
在开发和运维过程中,监控文件系统以检测文件的变化是一项常见需求。Python的Watchdog库为开发者提供了一个强大而简单的工具来实现这一功能。无论是自动备份、日志监控,还是开发工具的热重载,Watchdog都能帮助我们轻松实现。
1. 安装 Watchdog
在开始之前,确保你的环境中安装了Watchdog库。你可以通过以下命令安装:
pip install watchdog
2. 基本用法
Watchdog的核心组件是Observer
类和事件处理器FileSystemEventHandler
。让我们从一个简单的例子开始:
示例 1:监控文件的修改
import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
# 创建一个事件处理器类,继承自FileSystemEventHandler
class SimpleHandler(FileSystemEventHandler):
def on_modified(self, event):
if not event.is_directory:
print(f"文件被修改: {event.src_path}")
# 主程序
if __name__ == "__main__":
path = "." # 监控当前目录
event_handler = SimpleHandler()
observer = Observer()
observer.schedule(event_handler, path, recursive=False)
observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
代码说明:
- 导入模块:导入必要的模块,包括时间模块
time
、watchdog.observers
中的Observer
和watchdog.events
中的FileSystemEventHandler
。 - 定义事件处理器:创建一个
SimpleHandler
类,继承自FileSystemEventHandler
。在on_modified
方法中,判断事件不是目录,并打印出被修改文件的路径。 - 设置监控路径:设置
path
为当前目录"."
。 - 初始化观察者:创建
Observer
对象,并使用observer.schedule()
方法将事件处理器与路径绑定。 - 启动观察者:调用
observer.start()
启动监控。 - 保持运行:使用
while True
循环保持脚本运行,并通过try-except
块捕捉键盘中断以停止观察者。
3. 应用场景 1:自动备份
在文件被创建或修改时,将其自动复制到备份目录。
import os
import shutil
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
class BackupHandler(FileSystemEventHandler):
def __init__(self, dest_dir):
self.dest_dir = dest_dir
def on_modified(self, event):
if not event.is_directory:
self.backup_file(event.src_path)
def on_created(self, event):
if not event.is_directory:
self.backup_file(event.src_path)
def backup_file(self, src_path):
dest_path = os.path.join(self.dest_dir, os.path.basename(src_path))
shutil.copy2(src_path, dest_path)
print(f"文件已备份: {src_path} -> {dest_path}")
if __name__ == "__main__":
source_dir = "./source"
dest_dir = "./backup"
if not os.path.exists(dest_dir):
os.makedirs(dest_dir)
event_handler = BackupHandler(dest_dir)
observer = Observer()
observer.schedule(event_handler, source_dir, recursive=False)
observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
代码说明:
BackupHandler
类:继承自FileSystemEventHandler
,实现on_modified
和on_created
方法,用于监控文件的创建和修改。backup_file
方法:复制文件到备份目录。- 路径设置:定义
source_dir
为监控目录,dest_dir
为备份目录。如果备份目录不存在,则创建它。 - 初始化和启动观察者:同基本用法类似。
4. 应用场景 2:日志监控
监控日志文件的变化,并在发现特定关键词时发出警告。
import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
class LogMonitor(FileSystemEventHandler):
def __init__(self, log_file, keywords):
self.log_file = log_file
self.keywords = keywords
self.last_position = 0
def on_modified(self, event):
if event.src_path == self.log_file:
with open(self.log_file, 'r') as file:
file.seek(self.last_position)
new_content = file.read()
self.last_position = file.tell()
for line in new_content.splitlines():
if any(keyword in line for keyword in self.keywords):
print(f"警告: 发现关键词 - {line}")
if __name__ == "__main__":
log_file = "./app.log"
keywords = ["ERROR", "CRITICAL", "FATAL"]
event_handler = LogMonitor(log_file, keywords)
observer = Observer()
observer.schedule(event_handler, path='.', recursive=False)
observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
代码说明:
LogMonitor
类:继承自FileSystemEventHandler
,监控特定日志文件。on_modified
方法:在文件被修改时读取新内容,检查是否包含关键词。- 关键词设置:定义需要监控的关键词,如“ERROR”、“CRITICAL”等。
- 初始化观察者:与基本用法一致,但这里只监控特定日志文件。
5. 应用场景 3:开发工具的热重载
监控源代码文件的变化,自动重新加载模块。
import importlib
import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
# 假设这是我们要监控的模块
import my_module
class ReloadHandler(FileSystemEventHandler):
def on_modified(self, event):
if event.src_path.endswith('.py'):
print(f"检测到文件变化: {event.src_path}")
module_name = event.src_path[:-3].replace('/', '.').replace('\\', '.')
try:
module = importlib.import_module(module_name)
importlib.reload(module)
print(f"模块 {module_name} 已重新加载")
except ImportError:
print(f"无法重新加载模块 {module_name}")
if __name__ == "__main__":
path = "." # 监控当前目录
event_handler = ReloadHandler()
observer = Observer()
observer.schedule(event_handler, path, recursive=True)
observer.start()
try:
while True:
# 这里可以调用 my_module 中的函数
my_module.some_function()
time.sleep(5)
except KeyboardInterrupt:
observer.stop()
observer.join()
代码说明:
ReloadHandler
类:继承自FileSystemEventHandler
,检测.py
文件的修改。importlib
模块:用于动态加载和重新加载模块。- 路径设置:监控当前目录及其子目录中的所有Python文件。
6. 结论
Watchdog库为Python开发者提供了一个强大而简洁的工具,用于监控文件系统的变化。通过上述示例,我们可以看到它在自动备份、日志监控和开发工具热重载等场景中的应用。无论是简单的文件变化检测,还是复杂的自动化工作流,Watchdog都能够胜任。
希望这篇博客能帮助您掌握Watchdog的基本用法,并能在您的项目中发挥作用。如果您对某个特定示例有进一步的疑问或需求,请随时告诉我!