2016-11-04 3 views
2

Diese Frage wurde bereits mehrmals auf dieser Website gestellt und beantwortet, aber aus irgendeinem vagen Grund kam niemand mit einer relativ einfachen (meiner Meinung nach), prägnanter und wahrscheinlich mehr elegante Lösung. Vielleicht, weil die Lösung tatsächlich schlecht ist, aber das ist es, was ich versuche herauszufinden, wenn es schlecht ist, dann würde ich gerne wissen wie und warum. Eines der beliebtesten Antworten war:Erstellen einer Prüfsumme einer Datei in Python

def md5(fname): 
    hash_md5 = hashlib.md5() 
    with open(fname, "rb") as f: 
    for chunk in iter(lambda: f.read(4096), b""): 
     hash_md5.update(chunk) 
    return hash_md5.hexdigest() 

Es ist verständlich - wir wollen nicht die gesamte Datei in den Speicher zu laden, so dass wir sie in Stücke mit Hilfe eines Iterators und Lambda-Funktion lesen. Schön und einfach. Aber vermutlich konnten wir dies in einer einfacheren Art und Weise tun, durch Definieren der md5sum Funktion wie folgt:

def md5sum(fname): 
    md5 = hashlib.md5() 
    with open(fname, 'rb') as f: 
    for chunk in f: 
     md5.update(chunk) 
    return md5.hexdigest() 

Günstig, über eine offene Datei-Handle Iterieren uns eine Folge seiner Linien gibt, so konnten wir die ‚b‘ verwenden Präfix in open(fname, 'rb'), um über ein Byteobjekt zu iterieren. Was ist daran falsch?

+3

Es ist wahrscheinlich eine Frage, mit welcher Art von Dateien Sie es zu tun haben, insbesondere, ob es sich tatsächlich um eine ASCII-Datei oder eine Binärdatei handelt. Die ursprüngliche Version bietet mehr Kontrolle über die Chunk-Größe, während Ihre Version hier und da Zeilenvorschübe erwartet. Um große Dateien zu verarbeiten, verwende ich nicht nur 4K Daten gleichzeitig, sondern mindestens 100K, um sicherzustellen, dass beim "Chunking" kein erheblicher Aufwand entsteht. Ich hatte diese Erfahrung einmal mit dem Zip-Modul, und 100K ist heute nichts. –

+0

@ Dr.V Ich sehe, ich stimme fast allem zu, was du sagst, aber soweit ich sehen kann, funktioniert es gut für alle Arten von Dateien. – weeCoder

+1

@weeCoder Versuchen Sie, eine riesige Datei zu erstellen, die * nicht * das '\ x0a' Byte enthält und sehen ... das' für Chunk in f' zu 'chunk = f.read()' das Lesen der gesamten Datei in den Speicher abbaut . – Bakuriu

Antwort

2

Was Dr. V in den Kommentaren gesagt hat, ist korrekt.

Die Verwendung von for chunk in f: arbeitet mit Teilstücken, die in b'\n '== b'\x0A' enden. Das macht die Chunk-Größe sehr klein für Textdateien und völlig unvorhersehbar für typische Binärdateien: eine Binärdatei darf nicht enthalten beliebig0A Bytes. Wenn das passiert for chunk in f: liest einfach die ganze Datei in einem einzigen Stück.

Das 4k Chunk-Größe sollte in Ordnung sein, aber Sie könnten versuchen, eine Chunk-Größe von 64k oder 128k, um zu sehen, ob das die Geschwindigkeit verbessert. In einfachen Datenkopiertests (unter Verwendung von dd) habe ich wenig Nutzen bei der Verwendung größerer Chunk-Größen gefunden; Bedenken Sie, dass moderne Betriebssysteme gut in der Pufferung von Dateien sind & Caching. OTOH, ich betreibe eine ziemlich alte 32-Bit-Single-Core-Maschine.

Zum Thema Hashing großer Dateien interessiert Sie möglicherweise a program I wrote, die die OpenSSL-Crypto-Bibliothek verwendet, um einen SHA256-Hash für große Dateien durchzuführen. Das Feature dieses Programms ist, dass es fortsetzbar ist: Sie können es jederzeit stoppen und wenn Sie es neu starten, wird es den Hash-Prozess fortsetzen.

Und here's one, die hashlib verwendet, um die MD5- und SHA256-Hashes einer Datei gleichzeitig zu berechnen.

Verwandte Themen