Ich füge eindeutig nichts grundlegend Neues hinzu, aber ich habe diese Antwort hinzugefügt, bevor ich den Status eines Kommentars erreicht habe, und die Code-Regionen machen die Dinge klarer - jedenfalls speziell, um die Frage von @ Nemo aus der Antwort von Omnifarious zu beantworten:
Ich habe zufällig ein wenig über Prüfsummen nachgedacht (bin hierher gekommen, um nach Vorschlägen für Blockgrößen zu suchen) und habe festgestellt, dass diese Methode möglicherweise schneller ist als erwartet. Nehmen Sie die schnellste (aber ziemlich typische) timeit.timeit
oder /usr/bin/time
Ergebnis aus jeder von mehreren Methoden der Prüfsumme einer Datei von ca. 11 MB:
$ ./sum_methods.py
crc32_mmap(filename) 0.0241742134094
crc32_read(filename) 0.0219960212708
subprocess.check_output(['cksum', filename]) 0.0553209781647
md5sum_mmap(filename) 0.0286180973053
md5sum_read(filename) 0.0311000347137
subprocess.check_output(['md5sum', filename]) 0.0332629680634
$ time md5sum /tmp/test.data.300k
d3fe3d5d4c2460b5daacc30c6efbc77f /tmp/test.data.300k
real 0m0.043s
user 0m0.032s
sys 0m0.010s
$ stat -c '%s' /tmp/test.data.300k
11890400
Es sieht also so aus, als würden sowohl Python als auch / usr / bin / md5sum etwa 30 ms für eine 11-MB-Datei benötigen. Die relevante md5sum
Funktion ( md5sum_read
in der obigen Auflistung) ist der von Omnifarious ziemlich ähnlich:
import hashlib
def md5sum(filename, blocksize=65536):
hash = hashlib.md5()
with open(filename, "rb") as f:
for block in iter(lambda: f.read(blocksize), b""):
hash.update(block)
return hash.hexdigest()
Zugegeben, diese stammen aus einzelnen Läufen (die mmap
sind immer ein bisschen schneller, wenn mindestens ein paar Dutzend Läufe gemacht werden), und meine haben normalerweise ein Extra, f.read(blocksize)
nachdem der Puffer erschöpft ist, aber es ist einigermaßen wiederholbar und zeigt, dass dies md5sum
in der Befehlszeile der Fall ist nicht unbedingt schneller als eine Python-Implementierung ...
EDIT: Entschuldigung für die lange Verzögerung, ich habe mir das seit einiger Zeit nicht mehr angesehen, aber um die Frage von @ EdRandall zu beantworten, schreibe ich eine Adler32-Implementierung auf. Allerdings habe ich die Benchmarks dafür nicht ausgeführt. Es ist im Grunde das gleiche wie beim CRC32: Anstelle der Init-, Update- und Digest-Aufrufe ist alles ein zlib.adler32()
Aufruf:
import zlib
def adler32sum(filename, blocksize=65536):
checksum = zlib.adler32("")
with open(filename, "rb") as f:
for block in iter(lambda: f.read(blocksize), b""):
checksum = zlib.adler32(block, checksum)
return checksum & 0xffffffff
Beachten Sie, dass dies mit der leeren Zeichenfolge beginnen muss, da sich die Adler-Summen tatsächlich unterscheiden, wenn Sie bei Null beginnen, gegenüber ihrer Summe für ""
, 1
dh - CRC kann 0
stattdessen beginnen. Das AND
-ing wird benötigt, um eine 32-Bit-Ganzzahl ohne Vorzeichen zu erstellen, wodurch sichergestellt wird, dass in allen Python-Versionen derselbe Wert zurückgegeben wird.
md5sum
?