pythonにEOFを読み取らせて、sha1かmd5かにかかわらず、適切なハッシュを取得できます。助けてください。ここに私がこれまで持っているものがあります:
import hashlib
inputFile = raw_input("Enter the name of the file:")
openedFile = open(inputFile)
readFile = openedFile.read()
md5Hash = hashlib.md5(readFile)
md5Hashed = md5Hash.hexdigest()
sha1Hash = hashlib.sha1(readFile)
sha1Hashed = sha1Hash.hexdigest()
print "File Name: %s" % inputFile
print "MD5: %r" % md5Hashed
print "SHA1: %r" % sha1Hashed
TL; DRはバッファを使用して、大量のメモリを使用しません。
非常に大きなファイルを操作することのメモリへの影響を考慮すると、問題の核心に到達します。 pasztorpisti が指摘するように、この悪い男の子が2ギガバイトのRAMで2ギガバイトのRAMを使い回すのは望ましくありません。
import sys
import hashlib
# BUF_SIZE is totally arbitrary, change for your app!
BUF_SIZE = 65536 # lets read stuff in 64kb chunks!
md5 = hashlib.md5()
sha1 = hashlib.sha1()
with open(sys.argv[1], 'rb') as f:
while True:
data = f.read(BUF_SIZE)
if not data:
break
md5.update(data)
sha1.update(data)
print("MD5: {0}".format(md5.hexdigest()))
print("SHA1: {0}".format(sha1.hexdigest()))
Hashlibの便利なダンディ pdate method とともに、この悪い男の子のハッシュを64kbのチャンクで更新しています。この方法では、一度にすべての人をハッシュするのにかかる2GBよりもはるかに少ないメモリを使用します!
これをテストするには:
$ mkfile 2g bigfile
$ python hashes.py bigfile
MD5: a981130cf2b7e09f4686dc273cf7187e
SHA1: 91d50642dd930e9542c39d36f0516d45f4e1af0d
$ md5 bigfile
MD5 (bigfile) = a981130cf2b7e09f4686dc273cf7187e
$ shasum bigfile
91d50642dd930e9542c39d36f0516d45f4e1af0d bigfile
お役に立てば幸いです!
また、これらすべては右側のリンクされた質問で概説されています: Pythonで大きなファイルのMD5ハッシュを取得
一般的にpythonを書くときは、次の習慣を身につけるのに役立ちます pep-8 。たとえば、python変数では通常、キャメルケースではなくアンダースコアで区切られます。しかし、それは単なるスタイルであり、悪いスタイルを読まなければならない人を除いて、誰もそれらのことを本当に気にかけません...
ファイルのハッシュ値を正しく効率的に計算するには(Python 3):
'b'
を追加)、文字エンコードと行末変換の問題を回避します。readinto()
を使用して、バッファチャーニングを回避します。例:
import hashlib
def sha256sum(filename):
h = hashlib.sha256()
b = bytearray(128*1024)
mv = memoryview(b)
with open(filename, 'rb', buffering=0) as f:
for n in iter(lambda : f.readinto(mv), 0):
h.update(mv[:n])
return h.hexdigest()
ファイルをバイナリモードで開きます。open()
のデフォルトモードは'r'
で、「テキストモードで読み取り用に開く」です。テキストモードでは、データに対して改行変換が実行されるため、プラットフォーム固有のバグも発生する可能性がありますが、テキストモードの結果として発生する可能性のある問題は、「\ r\n」シーケンスが「\ n」シーケンスに置き換えられることですあなたが手に入れる文字列。特にバイナリファイルの場合、すべてのファイルに「\ r\n」シーケンスが含まれているわけではないため、バグは常に発生するわけではなく、キャッチするのは困難です。
openedFile = open(inputFile, 'rb')
ここには別の小さな問題があります。1つの大きなチャンクでファイルを読み取ります。小さい数キロバイトのチャンクで読み取ることにより、使用可能なメモリに収まらない場合でも非常に大きなファイルをハッシュできます。
私は単に提案します:
def get_digest(file_path):
h = hashlib.sha256()
with open(file_path, 'rb') as file:
while True:
# Reading is buffered, so we can read smaller chunks.
chunk = file.read(h.block_size)
if not chunk:
break
h.update(chunk)
return h.hexdigest()
ここにある他のすべての答えは複雑すぎるようです。 Pythonは読み取り時に既にバッファリングされているため(理想的な方法で、または基礎となるストレージに関する詳細情報がある場合はそのバッファリングを構成します)、ハッシュ関数が理想を見つけたチャンクで読み取る方が高速であるか、ハッシュ関数を計算するために、CPUをあまり使用しないようにします。したがって、バッファリングを無効にして自分でエミュレートしようとする代わりに、Pythonバッファリングを使用して、制御する必要があるものを制御します。つまり、データのコンシューマが理想的なハッシュブロックサイズを見つけます。
異なるアルゴリズムで大きなファイルをハッシュできるモジュールをプログラムしました。
pip3 install py_essentials
次のようなモジュールを使用します。
from py_essentials import hashing as hs
hash = hs.fileChecksum("path/to/the/file.txt", "sha256")
import hashlib
user = input("Enter ")
h = hashlib.md5(user.encode())
h2 = h.hexdigest()
with open("encrypted.txt","w") as e:
print(h2,file=e)
with open("encrypted.txt","r") as e:
p = e.readline().strip()
print(p)