好久沒有寫隨筆了,正好這兩天可以休整一下,藉此機會總結下最近使用python的小體會。
個人體會檔案校正在下載檔案時使用較多,在linux下最簡單的實現方式就是:
1 $ md5sum filename2 21c7ee192e64569ce43cfb869bdb2755 filename
當然在python當中也有對應的模組可以實現此功能,在python2.5之前可以使用 md5 模組,但是在python2.5以後就推薦使用 hashlib 來代替 md5 模組了。最簡單的實現代碼如下:
1 #!/usr/bin/env python 2 #coding : utf-8 3 4 import sys 5 import hashlib 6 7 def md5sum(filename): 8 file_object = open(filename, 'rb') 9 file_content = file_object.read()10 file_object.close()11 file_md5 = hashlib.md5(file_content)12 return file_md513 14 if __name__ == "__main__":15 file_md5 = md5sum(sys.argv[1])16 print file_md5.hexdigest()
竹風覺得有兩個地方值得注意:
一個是傳入 hashlib.md5() 的應該是 file_object.read() ,這樣才是對檔案內容產生md5校正碼,竹風剛開始就是沒有使用 read() 方法,而是傳入filename(這樣的md5是對檔案名稱產生的),導致產生的校正碼不對;
另外一個地方是,調用了 hashlib.md5() 後返回的是一個對象,想要獲得 linux 下 md5sum 同樣的效果,還要調用一下 hexdigest() 方法。
當然,上面的代碼考慮得不夠周全。如果要對一個比較大的檔案進行校正,將會把檔案內容一次讀入記憶體,造成效能上的缺陷。個人比較推薦從http://ryan-liu.iteye.com/blog/1530029提供的代碼,代碼如下:
1 #!/usr/bin/env python 2 #coding : utf-8 3 import hashlib 4 5 def md5hex(word): 6 """ MD5密碼編譯演算法,返回32位小寫16進位符號 7 """ 8 if isinstance(word, unicode): 9 word = word.encode("utf-8")10 elif not isinstance(word, str):11 word = str(word)12 m = hashlib.md5()13 m.update(word)14 return m.hexdigest()15 16 def md5sum(fname):17 """ 計算檔案的MD5值18 """19 def read_chunks(fh):20 fh.seek(0)21 chunk = fh.read(8096)22 while chunk:23 yield chunk24 chunk = fh.read(8096)25 else: #最後要將遊標放迴文件開頭26 fh.seek(0)27 m = hashlib.md5()28 if isinstance(fname, basestring) \29 and os.path.exists(fname):30 with open(fname, "rb") as fh:31 for chunk in read_chunks(fh):32 m.update(chunk)33 #上傳的檔案快取 或 已開啟的檔案流34 elif fname.__class__.__name__ in ["StringIO", "StringO"] \35 or isinstance(fname, file):36 for chunk in read_chunks(fname):37 m.update(chunk)38 else:39 return ""40 return m.hexdigest()
這段代碼就足夠強大了,每次讀入8k的內容,然後調用 update() ,來更新md5。
PS:至於為什麼是8k?這個就涉及到了IO大小方面的內容了。提供一篇文章,有興趣的可以看看瞭解下:http://blog.sina.com.cn/s/blog_6200c1440100vt4z.html