Python实现文件md5校验

来源:互联网 发布:图形工作站 知乎 编辑:程序博客网 时间:2024/05/14 15:38

Linux下校验文件MD5值,最简单的方法就是执行md5sum命令
md5sum filename
原本打算用subprocess调用系统命令来获取md5值,

[python] view plain copy
 print?
  1. import subprocess,shlex  
  2. cmd = "md5sum filename"  
  3. p = subprocess(shlex.split(cmd), stdout=subprocess.PIPE)  
  4. print p.stdout.read()  

不过python有自带的MD5模块hashlib,用起来简单很多,
Python Hashlib模块的使用说明 http://docs.python.org/2/library/hashlib.html
fd = hashlib.md5() #获取一个MD5加密算法对象
fd.update("string") #指定需要加密的字符串
fd.hexdigest() #获取加密后的16进制字符串

实例

[python] view plain copy
 print?
  1. #!/usr/bin/env python             
  2. #coding : utf-8 3  4 import sys   
  3. import hashlib                    
  4.                                   
  5. def md5sum(filename):             
  6.     fd = open(filename,"r")  
  7.     fcont = fd.r  
  8.     fd.close()           
  9.     fmd5 = hashlib.md5(fcont)  
  10.     return fmd5               
  11.                                   
  12. if __name__ == "__main__":        
  13.     fmd5 = md5sum(sys.argv[1])  
  14.     print fmd5.hexdigest()    

其中fmd5 = hashlib.md5(fcont)等同于
fmd5 = hashlib.md5(fcont)
fmd5.update(fcont)

需要注意的是,传入 hashlib.md5() 的应该是 文件内容而不是文件名 ,这样才是对文件内容产生md5校验码;
另外,调用了 hashlib.md5() 后返回的是一个对象,想要获得linux下 md5sum 同样的效果,还要调用一下 hexdigest() 方法。

但是,这个方法有点过于粗暴,当检验大文件时,一次将所有文件内容读入内存,实在耗费较大,
网上给出实例http://blog.csdn.net/shanliangliuxing/article/details/10115397,
根据文件块长度,依次获取文件内容读入内存,通过update()逐次更新校验值,

[python] view plain copy
 print?
  1. #!/usr/bin/env python 2  
  2.   
  3.  #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 chunk  
  24.              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()