我正在尝试编写一个小脚本来打印文件的校验和(使用 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
我做错了什么?我在 macOS High Sierra 上使用 python 3
最佳答案
有have been several issues Python 的历史(最近版本中大多数已修复)从文件句柄一次读取超过 2-4 GB(该问题的不可修复版本也出现在 32 位版本的 Python 上,它们只是缺少虚拟地址空间来读取数据)分配缓冲区;与 I/O 无关,但最常见的是占用大文件)。可用于散列的解决方法是以固定大小的 block 来更新散列(无论如何,这是一个好主意,因为依赖 RAM 大于文件大小是一个糟糕的主意)。最直接的方法是将代码更改为:
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
如果你喜欢,你可以使用两个参数 iter
和一些 functools
魔法来“简化”循环,替换整个 while
循环:
for block in iter(functools.partial(f.read, 64 * (1 << 20)), b''):
hasher.update(block)
或者在 Python 3.8+ 上,使用 the walrus operator, :=
它更简单,不需要导入或不可读的代码:
while block := f.read(64 * (1 << 20)): # Assigns and tests result in conditional!
hasher.update(block)
关于python - "OSError: [Errno 22] Invalid argument"当读取大文件时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46458537/