md5sum auf 17TB ca. 190.000 Files - MemoryError

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
SLRIT
User
Beiträge: 3
Registriert: Montag 26. Mai 2014, 08:58

Hallo zusammen,

ich habe da ein kleines Problem mit meinem Python-Script.

Ich habe ca. 17TB Daten von Maschine A auf Maschine B kopiert und möchte nun per md5sum schauen ob alle files korrekt kopiert wurden. Dafür habe ich mir ein kleines Script gebaut, welches ich per cygwin auf einem Windows-Rechner laufen lasse.

Hier mein Setup:
- Windows 7 x64 Pro
- 16GB RAM
- Intel S3420GP Board
- Intel Xeon X3460 @ 2.80GHz
- Cygwin x64 (1.7.29(0.272/5/3)
- Python 2.7.5

Ich habe mir Maschine A und Maschine B per Netzlaufwerk gemountet und möchte für beide (jeweils ein eigenes Script) die md5 Summen berechnen.
Bei den Dateien handelt es sich um Film-Schnitt-Dateien.Es sind ca. 190.000 Files und umfassen ca. 17TB Speicherplatz.

Ich gehe dabei so vor:
1. Alle Files auflisten und in eine .txt-Datei speichern
2. Für jede Zeile in diesem Textfile die md5 Summe berechnen und in eine zweite .txt-Datei speichern.

Allerdings treffe ich hier immer auf denselben Fehler - MemoryError - dieser Tritt erst nach einiger Zeit auf und teilweise bei unterschiedlichen Files.

Hier mein Code:

Code: Alles auswählen

#!/usr/bin/python

import os
import hashlib
import subprocess

path ='/cygdrive/e/'
output = "/cygdrive/c/Users/administrator/Desktop/md5list_maschineA.txt"
tempout = "/cygdrive/c/Users/administrator/Desktop/filelist_maschineA.txt"

def run_command(path):
        p1 = subprocess.Popen(["find", path, "-type", "f"], stdout=subprocess.PIPE)
        return iter(p1.stdout.readline, b'')

filelist = run_command(path)
md5list = []

tout = open(tempout, 'w', 1)

print "Let's get all the files we need"
for line in filelist:	
	line = line.strip()
	line = line.replace('\n','')	
	tout.write(line + "\n")	

tout.close()	

print "Now we calculate the md5sum"

tout = open(tempout, 'r', 1)
myFile = open(output, 'w', 1)

for line in tout:	
	rline = line.replace('\n','')
	tmp = hashlib.md5(open(rline).read()).hexdigest()		
	str = "%s | %s" %(line,tmp)
	str = str.replace('\n','')	
	myFile.write(str + '\n')

tout.close()	
myFile.close()
Ich wäre euch sehr dankbar wenn ihr mir helfen könntet.

Vielen Dank im voraus.
Boa
User
Beiträge: 190
Registriert: Sonntag 25. Januar 2009, 12:34

Hi,

Nachdem du das md5 Objekt erstellt hast, kannst du mit der Methode update die Daten Stückweise hinzufügen, damit du nicht die ganze Datei auf einmal im RAM hast.

Code: Alles auswählen

m = hashlib.md5()
with open(filepath) as file_to_hash:
    chunk = file_to_hash.read(1000)
    while chunk:
        m.update(chunk)
        chunk = file_to_hash.read(1000)
Ansonsten gibt es auch die einfache Variante das Tool md5deep zu verwenden.

Boa
SLRIT
User
Beiträge: 3
Registriert: Montag 26. Mai 2014, 08:58

Vielen Dank, werde ich gleich mal ausprobieren.
Sirius3
User
Beiträge: 17745
Registriert: Sonntag 21. Oktober 2012, 17:20

Besser noch das doppelte `read` einsparen:

Code: Alles auswählen

CHUNK_SIZE = 32768
md5_hash = hashlib.md5()
with open(filepath, 'rb') as file_to_hash:
    for chunk in iter(lambda: file_to_hash.read(CHUNK_SIZE), ''):
        md5_hash = m.update(chunk)
SLRIT
User
Beiträge: 3
Registriert: Montag 26. Mai 2014, 08:58

Besten Dank, ist Fehlerfrei durchgelaufen.
Antworten