這篇文章主要給大家介紹了關於利用Python如何寫一個基於MD5的文件監聽程序的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者使用python具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
前述
寫了一個基於MD5算法的文件監聽程序,通過不同的文件能夠生成不同的哈希函數,來實現實現判斷文件夾中的文件的增加、修改、刪除和過濾含有特定字符的文件名的文件。
需求說明
需要實現對一個文件夾下的文件的增加、修改和刪除的監控, 一旦發生上述操作,則進行提示。可以選擇過濾掉文件名中的特定字符和只監聽文件名中含有特定字符的文件。
簡述
首先,關於文件的增加、修改、刪除的反饋,可以想到利用MD5等類似的加密算法,因爲文件本身可以生成哈希值,只要文件內容或者文件名被修改過,就會生成和修改之前的哈希值不同的值,因此可以利用dict來存儲,一個文件名對應一個哈希值來存儲。其中增加和刪除就對應一個新增加的鍵值對和一個減少的鍵值對,而修改則可以理解爲刪除了舊的文件、增加了一個新的文件。
MD5算法可以直接利用第三方的 hashlib 庫來實現
m = hashlib.md5() myFile = open(full_path, 'rb') for line in myFile.readlines(): #以行爲單位不斷更新哈希值,避免文件過大導致一次產生大量開銷 m.update(line) #最後可以得到整個文件的哈希值
第二,關於濾掉文件名中的特定字符和只監聽文件名中含有特定字符的文件的功能,這個其實非常簡單,只需要用 list 分別對需要過濾和必須存在字符串進行存儲, 然後利用標誌位和字符串的子串包含性進行判斷就可以了,只有滿足條件的文件可以產生哈希值,產生哈希值也就意味着被監聽了。
判斷字符串中是否含有字串最常用的方法是 in 和 string 中的 find 方法,這裏就不再贅述,可以直接看下面的代碼
第三,因爲要同時監控多個文件夾,所以必須要利用到線程來處理,創建一個線程池來存儲線程, 線程利用了 threading 庫,並且實現一個線程類來處理線程的操作
class myListener(threading.Thread):
thread1 = myListener(mydir, json_list_include, json_list_exclude) #生成線程
說明
需要額外說明的一點是,在傳輸需要監聽的文件夾、必須包含的字段以及過濾字段的時候,我這裏是利用配置文件的形式來存儲的。說到底,是利用 toml 格式的數據進行的傳輸,toml格式和 json格式相比,用戶的可讀性更強一些,爲了便於博客展示,因此利用了 toml 格式
首先利用代碼生成了一下toml格式的文件,以後再想用的話,程序打包之後,可以直接修改配置文件來實現對程序的控制。
#!/usr/bin/env python # -*- coding:utf-8 -*- # Author: JYRoooy import collections import json import toml if __name__ == '__main__': myOrderDict = collections.OrderedDict myOrderDict = {'dict':[{'path':'E:/testing', 'include':['log_'], 'exclude': ['.swp', '.swx', 'tmp']},{'path':'E:/tmp', 'include':['.record'], 'exclude': ['.tmp']}]} myToml = toml.dump(myOrderDict, open('E:/python/code/PythonProject/tomlConfig.txt','w+'))
toml文件
格式說明, 一個 dict 對應一個監聽的文件夾和需要 過濾(exculde) 和 含有(include) 的字段,解釋一下,這裏的字段只是文件名的字段,監控 E:/testing 目錄下的文件,要包含 log_ 字段的文件,且不包含 .swp .swx .tmp 字段的文件, 並且監控 E:/tmp 目錄下的文件,要包含 .record 字段的文件,且不包含 .tmp 的文件。
代碼
完整程序的代碼,具體解釋可以看註釋
#!/usr/bin/env python # -*- coding:utf-8 -*- # Author: JYRoooy import toml import hashlib import os import sys import time import importlib import threading importlib.reload(sys) class myListener(threading.Thread): ''' 監聽類 ''' def __init__(self, input_dir, filt_in, filt_ex): #文件夾路徑,必須包含的字符,必須過濾的字符 threading.Thread.__init__(self) self.input_dir = input_dir self.filt_in = filt_in self.filt_ex = filt_ex self.dict = {} #用來存儲文件名和對應的哈希值 self.file_list = [] #存儲每一次掃描時的文件的文件名 self.pop_list = [] #存儲需要刪除的文件名 def run(self): while (1): #保證文件夾一直處於被監聽的狀態 for cur_dir, dirs, files in os.walk(self.input_dir): if files != []: self.file_list = [] for each_file_1 in files: each_file = each_file_1 if self.filt_in: #判斷文件名中是否有必須存在的字段 flagone = 0 for i in range(len(self.filt_in)): if self.filt_in[i] in each_file: flagone += 1 if flagone == 0: continue if self.filt_ex: #判斷文件名中是否有必須過濾掉的字段 flagtwo = 0 for i in range(len(self.filt_ex)): if self.filt_ex[i] in each_file: flagtwo = 1 if flagtwo==1: continue self.file_list.append(each_file) full_path = os.path.join(cur_dir, each_file) m = hashlib.md5() #實例化md5算法 myFile = open(full_path, 'rb') for line in myFile.readlines(): m.update(line) if each_file not in self.dict.keys(): #如果當前的dict中沒有這個文件,那麼就添加進去 self.dict[each_file] = m.hexdigest() #生成哈希值 print('文件夾:' +cur_dir+ "中的文件名爲:" + each_file + "的文件爲新文件" + time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))) if each_file in self.dict.keys() and self.dict[each_file] != m.hexdigest(): #如果當前dict中有這個文件,但是哈希值不同,說明文件被修改過,則需要對字典進行更新 print('文件夾:' +cur_dir+ "中的文件名爲:" + each_file + "的文件被修改於" + time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))) self.dict[each_file] = m.hexdigest() myFile.close() pop_list = [] for i in self.dict.keys(): if i not in self.file_list: #當字典中有不在當前文件名列表中時,說明文件已經被刪除 print('文件夾:' +cur_dir+ '中的文件名爲:' + i + "的文件已被刪除!!!" + time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))) pop_list.append(i) for i in pop_list: self.dict.pop(i) time.sleep(2) if __name__ == '__main__': threads = [] #用來存儲線程的線程池 with open('E:/python/code/PythonProject/tomlConfig.txt','r+') as f: #讀取toml格式的文件,並分解格式 mytoml = toml.load(f) myList = mytoml['dict'] for i in range(len(myList)): #因爲可能同時需要監聽多個文件夾,所以利用線程池處理多線程 json_list_include = [] json_list_exclude = [] mydir = myList[i]['path'] for sublist in range(len(myList[i]['include'])): json_list_include.append(myList[i]['include'][sublist]) for sublist in range(len(myList[i]['exclude'])): json_list_exclude.append(myList[i]['exclude'][sublist]) thread1 = myListener(mydir, json_list_include, json_list_exclude) #生成線程 threads.append(thread1) for t in threads: #開啓所有線程 t.start();
運行結果
兩個文件夾中的文件
第一次運行程序, 可以看到已經按照過濾規則完成了過濾和監聽
修改 loko.record 文件爲 loko.re,再來看結果
可以看到已經完成了監聽,因爲 loko.re 文件,並符合監聽的規則,所以不做出監聽,而我們前面說過,一個修改相當於一個刪除和一個新建操作,所以監聽程序提示原文件被刪除了
寫在後面
其他的效果我就不一一展示了。
程序也沒有實現很複雜的效果,代碼已經上傳 github -- https://github.com/JYRoy/MyFileListener (本地下載)
好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對神馬文庫的支持。