"OSError: [Errno 22] недопустимый аргумент" при чтении()огромного файла
Я пытаюсь написать небольшой скрипт, который печатает контрольную сумму файла (используя некоторый код из https://gist.github.com/Zireael-N/ed36997fd1a967d78cb2):
import sys
import os
import hashlib
file = '/Users/Me/Downloads/2017-11-29-raspbian-stretch.img'
with open(file, 'rb') as f:
contents = f.read()
print('SHA256 of file is %s' % hashlib.sha256(contents).hexdigest())
но я получаю следующее сообщение об ошибке:
Traceback (most recent call last):
File "checksum.py", line 8, in <module>
contents = f.read()
OSError: [Errno 22] Invalid argument
что я делаю не так? Я использую python 3 на macOS High Sierra
1 ответов
здесь были несколько вопросы за всю историю Python (большинство исправлено в последних версиях) чтение более 2-4 ГБ сразу из дескриптора файла (нефиксируемая версия проблемы также возникает на 32-битных сборках Python, где им просто не хватает виртуального адресного пространства для выделения буфера; не связанный с вводом-выводом, но чаще всего наблюдается прихлебывание больших файлов). Обходной путь, доступный для хэширования, - обновить хэш в кусках фиксированного размера (что в любом случае хорошая идея, так как рассчитывать на то, что ОЗУ больше размера файла, - плохая идея). Самый простой подход-изменить код на:
with open(file, 'rb') as f:
hasher = hashlib.sha256() # Make empty hasher to update piecemeal
while True:
block = f.read(64 * (1 << 20)) # Read 64 MB at a time; big, but not memory busting
if not block: # Reached EOF
break
hasher.update(block) # Update with new block
print('SHA256 of file is %s' % hasher.hexdigest()) # Finalize to compute digest
если вы чувствуете, фантазии, вы можете "упростить" цикл с помощью двух arg iter
и functools
магия, заменяющая всю while
петли с:
for block in iter(functools.partial(f.read, 64 * (1 << 20)), b''):
hasher.update(block)