python中watchdog文件监控与检测上传功能


Posted in Python onOctober 30, 2020

引言

上一篇介绍完了观察者模式的原理,本篇想就此再介绍一个小应用,虽然我也就玩了一下午,是当时看observer正好找到的,以及还有Django-observer,但Django很久没用了,所以提下这个作为一个笔记。

watchdog介绍

Watchdog的中文的“看门狗”,有保护的意思。最早引入Watchdog是在单片机系统中,由于单片机的工作环境容易受到外界磁场的干扰,导致程序“跑飞”,造成整个系统无法正常工作,因此,引入了一个“看门狗”,对单片机的运行状态进行实时监测,针对运行故障做一些保护处理,譬如让系统重启。这种Watchdog属于硬件层面,必须有硬件电路的支持。

Linux也引入了Watchdog,在Linux内核下,当Watchdog启动后,便设定了一个定时器,如果在超时时间内没有对/dev/Watchdog进行写操作,则会导致系统重启。通过定时器实现的Watchdog属于软件层面。

嗯,这样的嘛。好像上面这段话没啥用,连成为谈资都不行。我也是直接百度第一篇复制一段当做介绍,习惯使然。(手动狗头)

在python中文件监控主要有两个库,一个是pyinotify ( https://github.com/seb-m/pyinotify/wiki ),一个是watchdog(http://pythonhosted.org/watchdog/)。pyinotify依赖于Linux平台的inotify,后者则对不同平台的的事件都进行了封装。

watchdog使用

在python中可以直接通过pip安装:

pip install watchdog -i https://pypi.tuna.tsinghua.edu.cn/simple

watchdog主要采用观察者模型。主要有三个角色:observer,event_handler,被监控的文件夹。三者原本是独立的,主要通过observer.schedule函数将三者串起来。

事件类(event):

watchdog.events.FileSystemEvent(event_type, 
        src_path, 
        is_directory=False)
  • event_type为事件类型,为moved、deleted、created或modified的其中之一
  • src_path为触发该事件的文件或目录路径
  • is_directory为该事件是否由一个目录触发

watchdog能实现在不同平台下都能兼容,并监控相关事件,但是如果在Windows下,是有很多问题的,具体的会在后面提出,那懂了事件类,我们就可以看看事件处理方法:

那现在有了处

def on_created(event):
 print(f"hey, {event.src_path} has been created!")

def on_deleted(event):
 print(f"Someone deleted {event.src_path}!")

def on_modified(event):
 print(f"hey buddy, {event.src_path} has been modified")

def on_moved(event):
 print(f"ok ok ok, someone moved {event.src_path} to {event.dest_path}")

理事件的函数,就需要在主程序里创建一个监听程序了:

path = "."
 go_recursively = True
 my_observer = Observer()
 my_observer.schedule(my_event_handler, path, recursive=True)

observer.schedule(event_handler, path, recursive=False)相当于实例化监听对象,监控指定路径path,该路径触发任何事件都会调用event_handler来处理,如果path是目录,则recursive=True则会递归监控该目录的所有变化。每一次调用schedule()对一个路径进行监控处理就叫做一个watch,schedule()方法会返回这个watch,接着可以对这个watch做其他操作,如为该watch增加多个event处理器等。

那了解到这里,就可以写一个demo程序进行测试了:

from watchdog.observers import Observer
from watchdog.events import *
import time

class FileEventHandler(FileSystemEventHandler):
 def __init__(self):
  FileSystemEventHandler.__init__(self)

 def on_moved(self, event):
  if event.is_directory:
   print("directory moved from {0} to {1}".format(event.src_path,event.dest_path))
  else:
   print("file moved from {0} to {1}".format(event.src_path,event.dest_path))

 def on_created(self, event):
  if event.is_directory:
   print("directory created:{0}".format(event.src_path))
  else:
   print("file created:{0}".format(event.src_path))

 def on_deleted(self, event):
  if event.is_directory:
   print("directory deleted:{0}".format(event.src_path))
  else:
   print("file deleted:{0}".format(event.src_path))

 def on_modified(self, event):
  if event.is_directory:
   print("directory modified:{0}".format(event.src_path))
  else:
   print("file modified:{0}".format(event.src_path))

if __name__ == "__main__":
 observer = Observer()
 event_handler = FileEventHandler()
 observer.schedule(event_handler,r"D:\code\dingshirenwu",True)
 observer.start()
 try:
  while True:
   time.sleep(1)
 except KeyboardInterrupt:
  observer.stop()
 observer.join()

代码参考自python中文件变化监控-watchdog

不过这里只是监控了单个,我们可以通过循环来监控多个文件夹:

dirs = [r'D:\code\dingshirenwu', r'D:\code\tuiliu']
for dir in dirs:
 event_handler = FileEventHandler()
 observer.schedule(event_handler, dir, True)
observer.start()

到此为止,基本上已经知道这个模块到底怎么用了,但当我准备在事件里加一个上传机制的时候,发现Windows下的一些问题。Windows下watchdog并没有权限去监控文件是否完整。即我有一个大文件,2G的视频即使是内部百M传输,也需要几十秒的时间,但watchdog只能接收到文件创建的时间就立刻进行了文件上传,而不是同Linux并使用的inotify,似乎没有什么好的办法,我也只是能上传一些比较小的如图片等秒传秒下的文件,下面为我的代码:

import logging
import queue
import threading
import time
import watchdog.observers as observers
import watchdog.events as events
from ftplib import FTP

logger = logging.getLogger(__name__)

SENTINEL = None

def upload(f, remote_path, local_path):
 fp = open(local_path, "rb")
 buf_size = 1024
 f.storbinary("STOR {}".format(remote_path), fp, buf_size)
 fp.close()


class MyEventHandler(events.FileSystemEventHandler):
 def on_any_event(self, event):
  super(MyEventHandler, self).on_any_event(event)
  queue.put(event)
 def __init__(self, queue):
  self.queue = queue

def process(queue):
 while True:
  event = queue.get()
  logger.info(event)
  print(event.key)  # tuple
  ('modified', 'C:\\Users\\admin\\Desktop\\公司文件\\test\\GitHub\\isadb\\.idea', True)
  if (event.key)[0] == "created":
   upload(ftp, remote_path, event.src_path)


if __name__ == '__main__':
 logging.basicConfig(level=logging.DEBUG,
      format='[%(asctime)s %(threadName)s] %(message)s',
      datefmt='%H:%M:%S')
 ftp = FTP()
 ftp.connect("x.x.x.x", 21)  # 第一个参数可以是ftp服务器的ip或者域名,第二个参数为ftp服务器的连接端口,默认为21
 ftp.login(username, password)  # 匿名登录直接使用ftp.login()
 queue = queue.Queue()
 num_workers = 4
 pool = [threading.Thread(target=process, args=(queue,)) for i in range(num_workers)]
 for t in pool:
  t.daemon = True
  t.start()

 event_handler = MyEventHandler(queue)
 observer = observers.Observer()
 observer.schedule(
  event_handler,
  path=r'C:\Users\admin\Desktop\公司文件\test\GitHub\isadb',
  recursive=True)
 observer.start()
 try:
  while True:
   time.sleep(1)
 except KeyboardInterrupt:
  observer.stop()
 observer.join()

建立了一个工作线程池,而不是累积文件系统事件,该线程从一个公共队列中获取任务。上传文件我是写了一个类调用,但那个文件找不到了。。所以改用了函数,这里会有问题是:IOError: [Errno 13] Permission denied: u'D:\pycharm\test.mp4'

然后再Stack Overflow找到了一个解决方案:当上传一个大文件的时候,同时上传一个空文本,记录这个文件的大小,然后对这个文件进行轮询,只有当该文件的大小不再发生变化时,我们认为这个文件已经生成成功,这时再考虑上传,不过我也就写个demo,太麻烦了。。。如果有人有更好的方式,可以评论或者私信我。

到此这篇关于python中watchdog文件监控与检测上传的文章就介绍到这了,更多相关python watchdog监控文件内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python之PyUnit单元测试实例
Oct 11 Python
探究Python的Tornado框架对子域名和泛域名的支持
May 02 Python
Python实现的多线程http压力测试代码
Feb 08 Python
Python实现多属性排序的方法
Dec 05 Python
Python操作redis实例小结【String、Hash、List、Set等】
May 16 Python
使用python接入微信聊天机器人
Mar 31 Python
Win10下Python3.7.3安装教程图解
Jul 08 Python
python如何实现读取并显示图片(不需要图形界面)
Jul 08 Python
Python库安装速度过慢解决方案
Jul 14 Python
python的数学算法函数及公式用法
Nov 18 Python
PyTorch的Debug指南
May 07 Python
浅析Django接口版本控制
Jun 26 Python
GitHub上值得推荐的8个python 项目
Oct 30 #Python
python读取excel数据绘制简单曲线图的完整步骤记录
Oct 30 #Python
用python写PDF转换器的实现
Oct 29 #Python
python查询MySQL将数据写入Excel
Oct 29 #Python
Python 使用office365邮箱的示例
Oct 29 #Python
PyCharm2019.3永久激活破解详细图文教程,亲测可用(不定期更新)
Oct 29 #Python
Ubuntu 20.04安装Pycharm2020.2及锁定到任务栏的问题(小白级操作)
Oct 29 #Python
You might like
自己写了一个php检测文件编码的函数
2014/04/21 PHP
php实现读取内存顺序号
2015/03/29 PHP
PHP SOCKET编程详解
2015/05/22 PHP
Zend Framework分发器用法示例
2016/12/11 PHP
Javascript 面向对象特性
2009/12/28 Javascript
ASP.NET jQuery 实例16 通过控件CustomValidator验证RadioButtonList
2012/02/03 Javascript
jquery.artwl.thickbox.js  一个非常简单好用的jQuery弹出层插件
2012/03/01 Javascript
JS的replace方法介绍
2012/10/20 Javascript
JS实现QQ图片一闪一闪的效果小例子
2013/07/31 Javascript
验证手机号码的JS方法分享
2013/09/10 Javascript
javascript if条件判断方法小结
2014/05/17 Javascript
JavaScript计算某一天是星期几的方法
2015/08/05 Javascript
JavaScript基础教程——入门必看篇
2016/05/20 Javascript
原生js开发的日历插件
2017/02/04 Javascript
jQuery validata插件实现方法
2017/06/25 jQuery
vue做网页开场视频的实例代码
2017/10/20 Javascript
Vue在页面数据渲染完成之后的调用方法
2018/09/11 Javascript
JQuery Ajax跨域调用和非跨域调用问题实例分析
2019/04/16 jQuery
js常用正则表达式集锦
2019/05/17 Javascript
在layui中layer弹出层点击事件无效的解决方法
2019/09/05 Javascript
理解JavaScript中的Proxy 与 Reflection API
2020/09/21 Javascript
python批量提交沙箱问题实例
2014/10/08 Python
python 实现对文件夹内的文件排序编号
2018/04/12 Python
Python考拉兹猜想输出序列代码实践
2019/07/05 Python
pycharm显示远程图片的实现
2019/11/04 Python
HTML5之SVG 2D入门11—用户交互性(动画)介绍及应用
2013/01/30 HTML / CSS
Groupon西班牙官方网站:在线优惠券和交易,节省高达70%
2021/03/13 全球购物
JavaScript获取当前url根目录(路径)
2014/02/19 面试题
机电专业个人自荐信格式模板
2013/09/23 职场文书
继电保护工岗位职责
2014/01/05 职场文书
学习全国两会精神心得体会范文
2014/03/17 职场文书
医学生求职信
2014/07/01 职场文书
给客户的感谢信
2015/01/21 职场文书
纪委立案决定书
2015/06/24 职场文书
python爬取网页版QQ空间,生成各类图表
2021/06/02 Python
Redis实战之Lettuce的使用技巧详解
2022/12/24 Redis