2013-06-11 6 views
1

Я работал сегодня в простом скрипте для файлов контрольной суммы во всех доступных алгоритмах hashlib (md5, sha1 .....) Я написал его и отлаживал его с помощью Python2, но когда я решил перенести его на Python 3, он просто не сработает. Самое забавное, что он работает для небольших файлов, но не для больших файлов. Я думал, что есть проблема с тем, как я буферизую файл, но сообщение об ошибке - это то, что заставляет меня думать, что это связано с тем, как я делаю hexdigest (я думаю). Вот копия всего моего скрипта, поэтому не стесняйтесь копировать его, использовать его и помогать мне разобраться, в чем проблема. Я получаю ошибку при checksuming 250 мегабайтного файлаСценарий, работающий в Python2, но не в Python 3 (hashlib)

«кодек„UTF-8“не может декодировать байт 0xf3 в позиции 10: недопустимый продолжение байт»

Я Google, но может Не находите ничего, что его исправляет. Также, если вы видите лучшие способы его оптимизации, сообщите мне. Моя главная цель состоит в том, чтобы сделать работу на 100% в Python 3. Благодаря

#!/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, я просто положить его в случае, если вы хотите использовать его без необходимости modigy одну выше ,

#!/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() 

ответ

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 вместо getattr и hashlib.algorithms_available, чтобы проверить, если аргумент является действительным.

+0

Спасибо, я избегу hashlib.algorithms_available, поскольку он доступен только после 3.2 и недоступен в python2, но hashlib.new уверен, что выглядит более чистым. – JohnnyLoo

+0

BTW У меня есть эта ошибка, которую вы упомянули, но я решил ее, удалив часть .encode() при обновлении «dataChunk». Второй скрипт, который я добавил, должен работать для вас. – JohnnyLoo

+0

@JuanCarlos. Он не дает никаких ошибок, но возвращает неверный md5sum, если вы не откроете файл в двоичном режиме. –

 Смежные вопросы

  • Нет связанных вопросов^_^