前段时间写了一个Python脚本,目的是定时从目标位置获取文件,上传到阿里云OSS,为了避免重复上传相同的文件,我在每次获取到文件后加了一个获取其MD5的步骤,并用这个MD5在OSS中查找,如果有则放弃上传,没有则用这个MD5作为文件名进行上传。逻辑很简单,但不曾想没几天OSS就涨到将近1T,这就很迷惑了,因为目标文件总共就几百G。所以真相只有一个!MD5查重失效了!!!
看一下出错的代码:
import hashlib
import requests
class Archive:
def __init__(self):
self.hl = hashlib.md5()
def get_file(self):
file_getted = requests.get('xxxx', stream = True)
self.hl.update(file.content)
md5 = self.hl.hexdigest()
return md5
这个Archive类只在定时脚本初始化的时候实例化了一次,之后就一直用的这个实例
所以问题就出在只实例化一次这里,之后的每次update都会在之前update的基础上再update
>>> import hashlib
>>> hl = hashlib.md5()
>>> hl.update("abc".encode("utf-8"))
>>> hl.hexdigest()
'900150983cd24fb0d6963f7d28e17f72'
>>> hl.update("def".encode("utf-8"))
>>> hl.hexdigest()
'e80b5017098950fc58aad83c8c14978e'
>>> hl = hashlib.md5()
>>> hl.update("abcdef".encode("utf-8"))
>>> hl.hexdigest()
'e80b5017098950fc58aad83c8c14978e'
所以可以看出
>>> hl = hashlib.md5()
>>> hl.update("abc".encode("utf-8"))
>>> hl.update("def".encode("utf-8"))
与
>>> hl = hashlib.md5()
>>> hl.update(("abc"+"def").encode("utf-8"))
相等
因此,想要每次update都是独立的,则必须要每次update前都实例化出新的hl
所以,上面的代码要改成
import hashlib
import requests
class Archive:
def get_file(self):
file_getted = requests.get('xxxx', stream = True)
hl = hashlib.md5()
hl.update(file.content)
md5 = hl.hexdigest()
return md5
但总感觉每次都进行实例化再update有点多余
所以,一般的做法是:
import hashlib
import requests
class Archive:
def get_file(self):
file_getted = requests.get('xxxx', stream = True)
md5 = hashlib.md5(file.content).hexdigest()
return md5