【问题标题】:Script working in Python2 but not in Python 3 (hashlib)脚本在 Python2 中工作,但在 Python 3 (hashlib) 中不工作
【发布时间】:2013-06-07 22:00:55
【问题描述】:

我今天在一个简单的脚本中工作,以校验所有可用 hashlib 算法(md5,sha1.....)中的文件,我用 Python2 编写并调试它,但是当我决定将它移植到 Python 3 时,它就赢了不行。有趣的是它适用于小文件,但不适用于大文件。我认为缓冲文件的方式有问题,但是错误消息让我认为这与我执行 hexdigest 的方式有关(我认为)这是我整个脚本的副本,所以随意复制它,使用它并帮助我找出问题所在。校验 250 MB 文件时出现的错误是

“'utf-8'编解码器无法解码位置 10 中的字节 0xf3:无效的继续字节”

我用谷歌搜索它,但找不到任何修复它的东西。另外,如果您看到更好的优化方法,请告诉我。我的主要目标是在 Python 3 中 100% 工作。谢谢

#!/usr/local/bin/python33
import hashlib
import argparse

def hashFile(algorithm = "md5", filepaths=[], blockSize=4096):
    algorithmType = getattr(hashlib, algorithm.lower())() #Default: hashlib.md5()
    #Open file and extract data in chunks   
    for path in filepaths:
        try:
            with open(path) as f:
                while True:
                    dataChunk = f.read(blockSize)
                    if not dataChunk:
                        break
                    algorithmType.update(dataChunk.encode())
                yield algorithmType.hexdigest()
        except Exception as e:
            print (e)

def main():
    #DEFINE ARGUMENTS
    parser = argparse.ArgumentParser()
    parser.add_argument('filepaths', nargs="+", help='Specified the path of the file(s) to hash')
    parser.add_argument('-a', '--algorithm', action='store', dest='algorithm', default="md5", 
                        help='Specifies what algorithm to use ("md5", "sha1", "sha224", "sha384", "sha512")')
    arguments = parser.parse_args()
    algo = arguments.algorithm
    if algo.lower() in ("md5", "sha1", "sha224", "sha384", "sha512"):

这里是在 Python 2 中工作的代码,我只是把它放在你想使用它的情况下,而不必修改上面的代码。

#!/usr/bin/python
import hashlib
import argparse

def hashFile(algorithm = "md5", filepaths=[], blockSize=4096):
    '''
    Hashes a file. In oder to reduce the amount of memory used by the script, it hashes the file in chunks instead of putting
    the whole file in memory
    ''' 
    algorithmType = hashlib.new(algorithm)  #getattr(hashlib, algorithm.lower())() #Default: hashlib.md5()
    #Open file and extract data in chunks   
    for path in filepaths:
        try:
            with open(path, mode = 'rb') as f:
                while True:
                    dataChunk = f.read(blockSize)
                    if not dataChunk:
                        break
                    algorithmType.update(dataChunk)
                yield algorithmType.hexdigest()
        except Exception as e:
            print e

def main():
    #DEFINE ARGUMENTS
    parser = argparse.ArgumentParser()
    parser.add_argument('filepaths', nargs="+", help='Specified the path of the file(s) to hash')
    parser.add_argument('-a', '--algorithm', action='store', dest='algorithm', default="md5", 
                        help='Specifies what algorithm to use ("md5", "sha1", "sha224", "sha384", "sha512")')
    arguments = parser.parse_args()
    #Call generator function to yield hash value
    algo = arguments.algorithm
    if algo.lower() in ("md5", "sha1", "sha224", "sha384", "sha512"):
        for hashValue in hashFile(algo, arguments.filepaths):
            print hashValue
    else:
        print "Algorithm {0} is not available in this script".format(algorithm)

if __name__ == "__main__":
    main()

【问题讨论】:

    标签: utf-8 python-3.x md5 python-2.x hashlib


    【解决方案1】:

    我还没有在 Python 3 中尝试过,但是在 Python 2.7.5 中对于二进制文件我遇到了同样的错误(唯一的区别是我的使用的是 ascii 编解码器)。不用对数据块进行编码,而是直接以二进制模式打开文件:

    with open(path, 'rb') as f:
        while True:
            dataChunk = f.read(blockSize)
            if not dataChunk:
                break
            algorithmType.update(dataChunk)
        yield algorithmType.hexdigest()
    

    除此之外,我会使用hashlib.new 方法而不是getattrhashlib.algorithms_available 来检查参数是否有效。

    【讨论】:

    • 谢谢,我将避免使用 hashlib.algorithms_available,因为它仅在 3.2 之后可用并且在 python2 中不可用,但 hashlib.new 确实看起来更干净。
    • 顺便说一句,我得到了你提到的那个错误,但是我在更新“dataChunk”时删除了 .encode() 部分来解决它我添加的第二个脚本应该适合你
    • @JuanCarlos 它没有给出任何错误,但它返回一个不正确的 md5sum,除非您以二进制模式打开文件。
    • 这很奇怪,在我的系统中它可以工作。我在 Linux 中使用脚本和 md5sum 工具对 10 个文件进行了校验和,得到了完全相同的结果,与 sha1 相同。无论如何,无论如何我都在我的系统中工作,但为了安全起见,我将以二进制模式打开它。谢谢
    猜你喜欢
    • 1970-01-01
    • 2018-04-28
    • 2015-10-25
    • 1970-01-01
    • 1970-01-01
    • 2014-08-01
    • 2018-02-10
    • 2018-04-26
    • 2020-03-29
    相关资源
    最近更新 更多