Python 任何 UNC 文件的 hashlib MD5 摘要总是产生相同的散列

Python hashlib MD5 digest of any UNC file always yields same hash

下面的代码显示了在另一台机器上托管的 UNC 共享上的三个文件具有相同的哈希值。它还显示本地文件具有不同的哈希值。为什么会这样?我觉得有一些我不知道的UNC考虑。

Python 2.7.5 (default, May 15 2013, 22:44:16) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import hashlib
>>> fn_a = '\\some.host.com\Shares\folder1\file_a'
>>> fn_b = '\\some.host.com\Shares\folder1\file_b'
>>> fn_c = '\\some.host.com\Shares\folder2\file_c'
>>> fn_d = 'E:\file_d'
>>> fn_e = 'E:\file_e'
>>> fn_f = 'E:\folder3\file_f'
>>> f_a = open(fn_a, 'r')
>>> f_b = open(fn_b, 'r')
>>> f_c = open(fn_c, 'r')
>>> f_d = open(fn_d, 'r')
>>> f_e = open(fn_e, 'r')
>>> f_f = open(fn_f, 'r')
>>> hashlib.md5(f_a.read()).hexdigest()
'54637fdcade4b7fd7cabd45d51ab8311'
>>> hashlib.md5(f_b.read()).hexdigest()
'54637fdcade4b7fd7cabd45d51ab8311'
>>> hashlib.md5(f_c.read()).hexdigest()
'54637fdcade4b7fd7cabd45d51ab8311'
>>> hashlib.md5(f_d.read()).hexdigest()
'd2bf541b1a9d2fc1a985f65590476856'
>>> hashlib.md5(f_e.read()).hexdigest()
'e84be3c598a098f1af9f2a9d6f806ed5'
>>> hashlib.md5(f_f.read()).hexdigest()
'e11f04ed3534cc4784df3875defa0236'

编辑:为了进一步调查问题,我还使用来自另一台主机的文件进行了测试。看来换个host会改变结果。

>>> fn_h = '\\host\share\file'
>>> f_h = open(fn_h, 'r')
>>> hashlib.md5(f_h.read()).hexdigest()
'f23ee2dbbb0040bf2586cfab29a03634'

...但后来我在新主机上尝试了不同的文件,得到了新的结果!

>>> fn_i = '\\host\share\different_file'
>>> f_i = open(fn_i, 'r')
>>> hashlib.md5(f_i.read()).hexdigest()
'a8ad771db7af8c96f635bcda8fdce961'

所以,现在我真的很困惑。会不会和原主机是\host.com格式,新主机是\host格式有关?

如果您打算再次使用它,请使用 f1.seek(0),否则它将是一个完全读取的文件,再次调用 read() 只会 return 一个空字符串。

我没有重现你的问题。我在 Windows 7 上使用 Python 3.4 并使用以下测试脚本访问网络硬盘上的文件:

import sys, hashlib
def main():
    fn0 = r'\NAS\Public\Software\Backup\Test\Vagrantfile'
    fn1 = r'\NAS\Public\Software\Backup\Test\z.xml'
    with open(fn0, 'rb') as f:
        h0 = hashlib.md5(f.read())
        print(h0.hexdigest())
    with open(fn1, 'rb') as f:
        h1 = hashlib.md5(f.read())
        print(h1.hexdigest())

if __name__ == '__main__':
    sys.exit(main())

运行 这会产生两个不同的哈希值(如预期的那样):

c:\src\python>python hashtest.py
8af202dffb88739c2dbe188c12291e3d
2ff3db61ff37ca5ceac6a59fd7c1018b

如果读取文件内容 returns 远程文件的不同数据然后将该数据传递到 md5 必须导致不同的哈希值。您可能希望打印出每个文件的前 80 个字节,以检查您是否获得了预期的结果。

我根据大家提供的评论和回答做了一些额外的研究。我决定我需要研究代码的这两个特征的排列:

  1. 原始字符串文字用于路径名,即是否:
    A. 文件路径字符串是原始的,路径中有单个反斜杠,vs.
    B. 文件路径字符串不是原始的,路径中有双反斜杠

    (仅供那些不知道的人参考,原始字符串是由这样的 "r" 开始的字符串:r'This is a raw string'

  2. open功能模式为rrb
    (再次提醒那些不知道的人,rb 模式中的 b 表示以二进制形式读取文件。)

结果证明:

  • 字符串文字/反斜杠对不同文件的哈希值是否不同没有影响
  • 我的错误是没有以二进制模式打开文件。open 中使用 rb 模式时,我得到了不同的结果。

耶!并感谢您的帮助。