pythonでsha1を計算する方法 [プログラミング]
前に.NetのPython(名前忘れた)使ってハッシュ計算してみた時に、ファイル全部読んでハッシュ計算するという富豪的プログラミングをしてみたところ、300MB付近でOOMっぽい動きをしてしまって動かなかった。
原因は.net pythonのバイナリ列の実装に使っているStringクラスの制限のようだったのでまったく放置していた。
cpythonでは特にそういう問題もなかったし。
ただ、本来であれば分割して処理するのが筋であろうということで、調べたところ、以下の様なコードが正しいようだ。
ここでいうdが一気読みだとファイルサイズ分のバイト列になっているのが問題だった。
ハッシュ計算するsha1とかのアルゴリズムは、LinuxKernelやopensshの実装見てもわかるように3つの関数しか必要ない
init
update
final
で、pythonのようなスクリプト言語だとinitみたいなのはコンストラクタに入っているし
finalはhexdigestのような出力関数が呼ばれた時に実行されるのであろう。
またLinuxKernelなどでは一発読み込み対応で、init/update/finalを全部実効する関数も用意はされている。
ただ、今回のように読みこませるファイルが数百MBとか数TBとかの可能性がある場合は、init/update/finalを適切に呼び出す必要がある模様。
原因は.net pythonのバイナリ列の実装に使っているStringクラスの制限のようだったのでまったく放置していた。
cpythonでは特にそういう問題もなかったし。
ただ、本来であれば分割して処理するのが筋であろうということで、調べたところ、以下の様なコードが正しいようだ。
def calculate_hash( fullpath ): f = open(fullpath, 'rb') h = hashlib.sha1() while True: d = f.read(64*1024) #64KB if( d ): h.update(d) else: break f.close() print 'sha1 :' + h.hexdigest() return
ここでいうdが一気読みだとファイルサイズ分のバイト列になっているのが問題だった。
ハッシュ計算するsha1とかのアルゴリズムは、LinuxKernelやopensshの実装見てもわかるように3つの関数しか必要ない
init
update
final
で、pythonのようなスクリプト言語だとinitみたいなのはコンストラクタに入っているし
finalはhexdigestのような出力関数が呼ばれた時に実行されるのであろう。
またLinuxKernelなどでは一発読み込み対応で、init/update/finalを全部実効する関数も用意はされている。
ただ、今回のように読みこませるファイルが数百MBとか数TBとかの可能性がある場合は、init/update/finalを適切に呼び出す必要がある模様。
コメント 0