python 使用 watchdog 實現類似 Linux 中 tail -f 的功能

一、代碼實現

import logging
import os
import threading
import timefrom watchdog.events import FileSystemEventHandler
from watchdog.observers import Observerlogger = logging.getLogger(__name__)class LogWatcher(FileSystemEventHandler):def __init__(self, log_file, on_modified_callback=None):""""初始化 LogWatcher 類的實例。參數:- log_file:日志文件的路徑- on_modified_callback:可選的回調函數,在文件修改時調用屬性:- log_file:日志文件的路徑- file_object:日志文件對象- on_modified_callback:文件修改回調函數- last_line:最后一行文本- observer:觀察者對象- match_string:需要匹配的字符串- stop_watching:停止監視的標志"""self.log_file = log_fileself.file_object = open(log_file, 'rb')self.on_modified_callback = on_modified_callbackself.last_line = self.get_last_line()  # 初始化時獲取最后一行文本self.observer = Observer()self.observer.schedule(self, ".", recursive=False)self.match_string = Noneself.stop_watching = Falsedef start(self):"""啟動觀察者對象,開始監視文件變化。"""self.observer.start()def stop(self):"""停止觀察者對象,結束監視文件變化。"""self.observer.stop()self.observer.join()self.file_object.close()def get_last_line(self):"""獲取日志文件的最后一行文本。它通過將文件指針移動到文件末尾,然后逐個字符向前搜索,直到找到換行符為止。返回值:- 最后一行文本,如果文件為空則返回None"""# 將文件指針移動到文件末尾self.file_object.seek(0, os.SEEK_END)# 獲取當前文件指針的位置(此時指針在最后一行的末尾)position = self.file_object.tell()try:# 嘗試向前移動兩個字節new_position = max(position - 2, 0)self.file_object.seek(new_position, os.SEEK_SET)except OSError as e:# 如果發生錯誤,可能是文件太小,返回Nonereturn None# 逐個字符向前搜索,確保文件指針最終停在當前行的第一個字符處while True:# read(1)讀取的是指針位置的下一個字符,每次調用read(1)都會讀取一個字符,并將指針向后移動一個字符的位置。char = self.file_object.read(1).decode('utf-8', errors='ignore')if char == '\n':breakif new_position == 0:# 如果已經到達文件開頭,跳出循環break# 嘗試向前移動一個字節位置,確保不越界到文件開頭new_position = max(new_position - 1, 0)# 將文件指針移動到新的位置self.file_object.seek(new_position, os.SEEK_SET)# last_line = self.file_object.readline().decode('utf-8', errors='ignore').strip()last_line = self.file_object.read(position - new_position).decode('utf-8', errors='ignore').strip()# 輸出調試信息logger.debug(f'Reading line: {last_line}')return last_linedef on_modified(self, event):"""on_modified方法是FileSystemEventHandler的回調方法,當日志文件發生變化時,都會調用這個方法。參數:- event:文件變化事件對象"""# 注意,這里一個要用絕對路徑比較,不能直接使用 event.src_path == self.log_file,# event.src_path == self.log_file 的值為false# if event.src_path == self.log_file:if os.path.abspath(event.src_path) == os.path.abspath(self.log_file):# 在文件發生變化時,實時獲取最后一行文本self.last_line = self.get_last_line()# 用戶可在外部傳入一個回調方法,在文本發生變化時執行該事件if self.on_modified_callback:self.on_modified_callback()# 調用基類的同名方法,以便執行基類的默認行為super(LogWatcher, self).on_modified(event)def tail_last_line_and_match(self, match_string=None, max_match_seconds=10):"""實時監控日志文件的變化,并實時獲取最后一行文本。如果匹配到指定的字符串,停止監視。參數:- match_string:需要匹配的字符串"""self.match_string = match_stringself.start()end_time = time.time() + max_match_secondstry:while not self.stop_watching and time.time() <= end_time:if self.match_string and self.match_string in self.last_line:self.stop_watching = Trueexcept KeyboardInterrupt:passself.stop_watching = True  # 停止監視循環def write_logs(log_file):"""在新線程中寫入日志"""for i in range(10):with open(log_file, 'a') as file:file.write(f'New log entry {i}\n')time.sleep(1)  # 每秒寫入一次日志if __name__ == '__main__':import logginglogging.basicConfig(level=logging.DEBUG)log_file = 'demo.log'# 創建日志文件并寫入示例日志with open(log_file, 'w') as file:file.write('This is the first line of the log.\n')file.write('This is the second line of the log.\n')log_watcher = LogWatcher(log_file)# 啟動新線程寫入日志write_thread = threading.Thread(target=write_logs, args=(log_file,))write_thread.start()# 啟動實時監控日志文件變化,并打印最后一行文本,直到匹配到指定字符串或超時才停止監視log_watcher.tail_last_line_and_match(match_string='New log entry 9', max_match_seconds=20)# 等待寫入線程結束write_thread.join()

三、Demo驗證

運行代碼,控制臺的輸出結果:

DEBUG:__main__:Reading line: This is the second line of the log.
DEBUG:__main__:Reading line: New log entry 0
DEBUG:__main__:Reading line: New log entry 1
DEBUG:__main__:Reading line: New log entry 2
DEBUG:__main__:Reading line: New log entry 3
DEBUG:__main__:Reading line: New log entry 4
DEBUG:__main__:Reading line: New log entry 5
DEBUG:__main__:Reading line: New log entry 6
DEBUG:__main__:Reading line: New log entry 7
DEBUG:__main__:Reading line: New log entry 8
DEBUG:__main__:Reading line: New log entry 9Process finished with exit code 0

歡迎技術交流:

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/207709.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/207709.shtml
英文地址,請注明出處:http://en.pswp.cn/news/207709.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

《opencv實用探索·十五》inRange二值化圖像

opencv接口如下&#xff1a; void inRange(InputArray src, InputArray lowerb, InputArray upperb, OutputArray dst);函數實現二值化功能&#xff0c;主要是將在兩個閾值內的像素值設置為白色&#xff08;255&#xff09;&#xff0c;而不在閾值區間內的像素值設置為黑色&am…

一篇文章帶你快速入門 Nuxt.js 服務端渲染

1. Nuxt.js 概述 1.1 我們一起做過的SPA SPA&#xff08;single page web application&#xff09;單頁 Web 應用&#xff0c;Web 不再是一張張頁面&#xff0c;而是一個整體的應用&#xff0c;一個由路由系統、數據系統、頁面&#xff08;組件&#xff09;系統等等&#xff0…

什么是HTTPS加密協議?HTTPS安全傳輸原理,SSL和TLS介紹,NGINX如何配置SSL證書

HTTPS介紹 HTTPS是超文本傳輸協議&#xff08;HTTP&#xff09;的安全版本。它使用SSL&#xff08;安全套接層&#xff09;或TLS&#xff08;傳輸層安全&#xff09;加密協議來保護數據傳輸的安全性和機密性&#xff0c;以防止未經授權的訪問和竊聽。HTTPS協議通常用于處理敏感…

HbuilderX使用Uniapp+Vue3安裝uview-plus

如果你是vue2版本想使用uniapp去配置uviewui庫可以參考之前的文章 小程序的第三方ui庫推薦較多的還是uview的&#xff0c;看起來比較美觀&#xff0c;功能也比較完善&#xff0c;下面將提一下Vue3安裝uview-plus庫的教程 創建項目 安裝 首先進入官網 uView-Plus 直接下載并導…

預訓練--微調

預訓練–微調 一個很簡單的道理&#xff0c;如果我們的模型是再ImageNet下訓練的&#xff0c;那么這個模型一定是會比較復雜的&#xff0c;意思就是這個模型可以識別到很多種類別的即泛化能力很強&#xff0c;但是如果要它精確的識別是否某種類別&#xff0c;它的表現可能就不…

07-2 Python模塊和命名空間

1. 模塊 概念&#xff1a;其實就是一個Python文件&#xff0c;正常文件有的變量&#xff0c;函數&#xff0c;類&#xff0c;模塊都有 功能:模塊可以被其它程序引入&#xff0c;以使用該模塊中的函數等功能。 示例&#xff1a;test-module.py調用mymodule.py模塊中的now_time…

充電樁IC

充電樁IC 電子元器件百科 文章目錄 充電樁IC前言一、充電樁IC是什么二、充電樁IC的類別三、充電樁IC的應用實例四、充電樁IC的工作原理總結前言 充電樁IC的設計和功能會根據不同的充電協議和市場需求進行調整和定制。目前市場上有許多不同型號和廠家的充電樁IC可供選擇,以滿足…

一篇文章帶你快速入門 Vue 核心語法

一篇文章帶你快速入門 Vue 核心語法 一、為什么要學習Vue 1.前端必備技能 2.崗位多&#xff0c;絕大互聯網公司都在使用Vue 3.提高開發效率 4.高薪必備技能&#xff08;Vue2Vue3&#xff09; 二、什么是Vue 概念&#xff1a;Vue (讀音 /vju?/&#xff0c;類似于 view) …

Mysql 日期函數大全

一、時間函數 &#xff08;一&#xff09;、獲取當前時間 1、NOW() 獲取當前日期和時間&#xff0c;在程序一開始執行便拿到時間 返回格式 YYYY-MM-DD hh:mm:ss eg&#xff1a; NOW() 得到 2023-12-03 12:20:02 NOW(),SLEEP(2),NOW() 得到 2023-12-03 12:20:02 | 0 | 2023-…

目標檢測——OverFeat算法解讀

論文&#xff1a;OverFeat: Integrated Recognition, Localization and Detection using Convolutional Networks 作者&#xff1a;Pierre Sermanet, David Eigen, Xiang Zhang, Michael Mathieu, Rob Fergus, Yann LeCun 鏈接&#xff1a;https://arxiv.org/abs/1312.6229 文章…

Go語言-讓我印象深刻的13個特性

我們正在加速進入云原生時代&#xff0c;Go語言作為云原生的一塊基石&#xff0c;確有它的獨到之處。本文介紹Go語言的幾個讓我印象深刻的特性。 1、兼顧開發效率和性能 Go語言兼顧開發效率和性能。可以像Python那樣有很快的開發速度&#xff0c;也可以像C那樣有很快的執行速…

SpringAOP專欄二《原理篇》

上一篇SpringAOP專欄一《使用教程篇》-CSDN博客介紹了SpringAop如何使用&#xff0c;這一篇文章就會介紹Spring AOP 的底層實現原理&#xff0c;并通過源代碼解析來詳細闡述其實現過程。 前言 Spring AOP 的實現原理是基于動態代理和字節碼操作的。不了解動態代理和字節碼操作…

【C語言】函數遞歸詳解(一)

目錄 1.什么是遞歸&#xff1a; 1.1遞歸的思想&#xff1a; 1.2遞歸的限制條件&#xff1a; 2.遞歸舉例&#xff1a; 2.1舉例1&#xff1a;求n的階乘&#xff1a; 2.1.1 分析和代碼實現&#xff1a; 2.1.2圖示遞歸過程&#xff1a; 2.2舉例2&#xff1a;順序打印一個整數的…

機器學習---集成學習的初步理解

1. 集成學習 集成學習(ensemble learning)是現在非常火爆的機器學習方法。它本身不是一個單獨的機器學 習算法&#xff0c;而是通過構建并結合多個機器學習器來完成學習任務。也就是我們常說的“博采眾長”。集 成學習可以用于分類問題集成&#xff0c;回歸問題集成&#xff…

多線程并發Ping腳本

1. 前言 最近需要ping地址&#xff0c;還是挺多的&#xff0c;就使用python搞一個ping腳本&#xff0c;記錄一下&#xff0c;以免丟失了。 2. 腳本介紹 首先檢查是否存在True.txt或False.txt文件&#xff0c;并在用戶確認后進行刪除&#xff0c;然后從IP.txt的文件中讀取IP地…

CSS——sticky定位

1. 大白話解釋sticky定位 粘性定位通俗來說&#xff0c;它就是相對定位relative和固定定位fixed的結合體&#xff0c;它的觸發過程分為三個階段 在最近可滾動容器沒有觸發滑動之前&#xff0c;sticky盒子的表現為相對定位relative【第一階段】&#xff0c; 但當最近可滾動容…

【MATLAB】tvfEMD信號分解+FFT+HHT組合算法

有意向獲取代碼&#xff0c;請轉文末觀看代碼獲取方式~也可轉原文鏈接獲取~ 1 基本定義 TVFEMDFFTHHT組合算法是一種結合了總體變分模態分解&#xff08;TVFEMD&#xff09;、傅里葉變換&#xff08;FFT&#xff09;和希爾伯特-黃變換&#xff08;HHT&#xff09;的信號分解方…

vivado時序方法檢查8

TIMING-30 &#xff1a; 生成時鐘所選主源管腳欠佳 生成時鐘 <clock_name> 所選的主源管腳欠佳 &#xff0c; 時序可能處于消極狀態。 描述 雖然 create_generated_clock 命令允許您指定任意參考時鐘 &#xff0c; 但是生成時鐘應引用在其直接扇入中傳輸的時鐘。此…

電子學會C/C++編程等級考試2021年06月(五級)真題解析

C/C++等級考試(1~8級)全部真題?點這里 第1題:數字變換 給定一個包含5個數字(0-9)的字符串,例如 “02943”,請將“12345”變換到它。 你可以采取3種操作進行變換 1. 交換相鄰的兩個數字 2. 將一個數字加1。如果加1后大于9,則變為0 3. 將一個數字加倍。如果加倍后大于…

JS--異步的日常用法

目錄 JS 異步編程并發&#xff08;concurrency&#xff09;和并行&#xff08;parallelism&#xff09;區別回調函數&#xff08;Callback&#xff09;GeneratorPromiseasync 及 await常用定時器函數 JS 異步編程 并發&#xff08;concurrency&#xff09;和并行&#xff08;p…