Seite 1 von 2
MemoryError lösen
Verfasst: Montag 27. Dezember 2010, 23:33
von microkernel
Hallo,
ich hab vor kurzen ein kleines Script geschrieben welches von jeder Datei auf meinen Computer eine MD5, SHA1 und eine SHA256 Hashsumme erstellt und diese in eine MySQL Datenbank einträgt. Danach sollen diese Hashsummen mit einer Datenbank verglichen werden in welcher Hashsummen von Malware eingetragen ist. Das Script welches die Hashsummen von mein Dateien erstellt sieht wie folgt aus:
Code: Alles auswählen
import hashlib
import sys
import os
import MySQLdb
def main():
walker = os.walk(os.environ["SYSTEMDRIVE"] + os.sep)
while True:
try:
curdir = walker.next()
except StopIteration:
break
finally:
for f in curdir[2]:
insert(curdir[0], f)
def insert(path, fname):
absolute = path + os.sep + fname
try:
content = open(absolute, "r").read()
md5 = hashlib.md5(content).hexdigest()
sha256 = hashlib.sha256(content).hexdigest()
sha1 = hashlib.sha1(content).hexdigest()
except IOError:
md5 = sha256 = sha1 = ""
cursor.execute("INSERT INTO files VALUES (%s, %s, %s, %s, %s)",
(fname, absolute, md5, sha256, sha1))
connection.commit()
if __name__ == "__main__":
try:
connection = MySQLdb.connect(
"localhost",
"root",
"",
"system")
except:
sys.stdout.write("Can not connect to MySQL database (adress: localhost, user: root, password: '', table: system)")
sys.exit(0)
cursor = connection.cursor()
sys.stdout.write("Running... Pleas be patient")
main()
Nun erhalte ich jedoch nach zirka 70.000 eingetragenen Datensätzen erscheint bei mir ein MemoryError. Mir ist bekannt was für ein Fehler das ist und was das bedeuted allerdings verstehe ich nicht warum dieser Fehler auftritt.
Kann mir da vielleicht jemand erklären warum dieser Fehler auftritt und wie ich ihn beheben kann?
Liebe Grüße
microkernel
Re: MemoryError lösen
Verfasst: Montag 27. Dezember 2010, 23:51
von DasIch
Hast du schonmal daran gedacht dass es Dateien auf deinem System geben könnte die nicht komplett in deinen Speicher passen?
Abgesehen davon dass dein Script wahrscheinlich nur auf CPython läuft ohne das Limit an geöffneten Dateien zu erreichen.
Re: MemoryError lösen
Verfasst: Montag 27. Dezember 2010, 23:53
von lunar
Dieser Fehler tritt nicht zufällig bei der Verarbeitung einer besonders großen Datei auf?
Dazu die üblichen Hinweise: Pfade setzt man mit "os.path.join()" zusammen, Dateien öffnet und schließt man mit der "with"-Anweisung, Ausnahmen konkret behandeln und nicht alle pauschal (kein "except" ohne Ausnahmespezifikation oder zumindest logging des Tracebacks), usw. Und was in Gottes Namen hast Du Dir den bei "main()" gedacht?!
Re: MemoryError lösen
Verfasst: Dienstag 28. Dezember 2010, 15:29
von Py-Prog
DasIch hat geschrieben:Hast du schonmal daran gedacht dass es Dateien auf deinem System geben könnte die nicht komplett in deinen Speicher passen?
Na und, Der DS (Lite) kann auch eine über ein GB große datei offnen, und der hat auch nur 4 MB RAM. Oder liegt das an dem Flash speicher?
@microkernel jetzt weiß doch jeder den inhalt der Datei, jetzt braucht man nur noch eine Virus der die Festplatte nach dem Inhalt durchsucht und die Datei Löscht.

Re: MemoryError lösen
Verfasst: Dienstag 28. Dezember 2010, 15:32
von DasIch
Py-Prog hat geschrieben:DasIch hat geschrieben:Hast du schonmal daran gedacht dass es Dateien auf deinem System geben könnte die nicht komplett in deinen Speicher passen?
Na und, Der DS (Lite) kann auch eine über ein GB große datei offnen, und der hat auch nur 4 MB RAM.
(Echt kein Scherz)
Wieso sollte er es auch nicht können?
Irgendwie hab ich ja das Gefühl es steht ums Textverständnis im Allgemeinen deutlich schlechter als von Pisa ermittelt.
Re: MemoryError lösen
Verfasst: Dienstag 28. Dezember 2010, 15:43
von Py-Prog
Wieso sollte dann ein PC mit 2 GB ram keine 2,35 GB Datei Öffnen Können?
Re: MemoryError lösen
Verfasst: Dienstag 28. Dezember 2010, 15:54
von BlackJack
@Py-Prog: Es geht nicht darum ob die Datei geöffnet werden kann, sondern darum sie nach dem Öffnen komplett in den Speicher zu lesen. Und Du wirst doch verstehen das der DS keine 1 GB-Datei komplett in nur 4 MB Speicher einlesen kann, oder!? Genau so wenig kann ein PC eine deutlich grössere Datei als Hauptspeicher vorhanden ist, in selbigen einlesen.
In beiden Fällen kann man aber kleinere Teile der Datei einlesen und verarbeiten. Und das kann man so oft machen, bis man alle Daten der Datei einmal im Speicher hatte und die Prüfsumme mit den Daten aktualisiert hat um so eine Prüfsumme über die gesamte Datei zu bekommen.
Re: MemoryError lösen
Verfasst: Dienstag 28. Dezember 2010, 16:03
von cofi
Mal was zum Code:
Wenn ich nichts uebersehe liesse sich
Code: Alles auswählen
def main():
walker = os.walk(os.environ["SYSTEMDRIVE"] + os.sep)
while True:
try:
curdir = walker.next()
except StopIteration:
break
finally:
for f in curdir[2]:
insert(curdir[0], f)
als
Code: Alles auswählen
def main():
walker = os.walk(os.environ["SYSTEMDRIVE"])
for dir, _, files in walker:
for f in files:
insert(dir, f)
schreiben.
Re: MemoryError lösen
Verfasst: Donnerstag 30. Dezember 2010, 00:03
von microkernel
@cofi und lunar
Oh gott

manchmal denke ich etwas umständlich
Ich hab das eigentliche Problem jetzt so gelöst:
Code: Alles auswählen
[...]
try:
with open(absolute, "r") as f:
md5 = hashlib.md5()
sha256 = hashlib.sha256()
sha1 = hashlib.sha1()
content = 1
while content != "":
content = f.read(1048576 * 500) # 500 MB
md5.update(content)
sha256.update(content)
sha1.update(content)
md5 = md5.hexdigest()
sha256 = sha256.hexdigest()
sha1 = sha1.hexdigest()
except IOError:
md5 = sha256 = sha1 = ""
[...]
Re: MemoryError lösen
Verfasst: Donnerstag 30. Dezember 2010, 20:03
von microkernel
Hallo,
ich hab jetzt noch eine kleine Frage: Wie könnte ich den Ablauf beschleunigen? Könnte ich vielleicht eine C-Lib für die Hashsummen berechnung nehmen? Threads währen hier doch wenig hilfreich, oder?
Lg
microkernel
Re: MemoryError lösen
Verfasst: Donnerstag 30. Dezember 2010, 20:24
von lunar
Du kannst dieses Programm nicht wesentlich beschleunigen, denn die Festplatte ist hier der Flaschenhals. Im Übrigen ist hashlib bereits in C implementiert.
Re: MemoryError lösen
Verfasst: Donnerstag 30. Dezember 2010, 20:28
von Py-Prog
Du kaufst dir etwas Flüssigstickstoff um damit die übertaktete CPU zu kühlen.
Oder du kompilierst den Code, dann wird es normal auch schneller, aber selbst dann wird es noch einige Zeit dauern. Da hilft dann nur noch bessere Hardware.
Re: MemoryError lösen
Verfasst: Donnerstag 30. Dezember 2010, 20:51
von HerrHagen
Du nimmst dir einen schneller zu berechnenden Hash-Wert. Du musst ja bei deiner Anwendung keine kryptographischen Anforderungen erfüllen.
Re: MemoryError lösen
Verfasst: Donnerstag 30. Dezember 2010, 20:53
von Py-Prog
HerrHagen hat geschrieben:Du nimmst dir einen schneller zu berechnenden Hash-Wert. Du musst ja bei deiner Anwendung keine kryptographischen Anforderungen erfüllen.
Und was ist wenn die Datenbank aber genau soeinen Hash braucht?
Re: MemoryError lösen
Verfasst: Donnerstag 30. Dezember 2010, 21:11
von HerrHagen
Warum sollte das so sein? Ich denke es geht darum Malware zu idendifizieren? In eine Datenbank kann man alles mögliche speichern.
Re: MemoryError lösen
Verfasst: Donnerstag 30. Dezember 2010, 21:24
von Py-Prog
Ich meine die Datenbank mit der es vergleichen will, die wird er ja wohl nicht selber erstellt haben.
Re: MemoryError lösen
Verfasst: Donnerstag 30. Dezember 2010, 23:54
von microkernel
Py-Prog hat geschrieben:Ich meine die Datenbank mit der es vergleichen will, die wird er ja wohl nicht selber erstellt haben.
Da stimmt.

Mir stehen nur SHA256, SHA1 und MD5 Hashsummen zum vergleichen zur Verfügung.
Py-Prog hat geschrieben:Oder du kompilierst den Code, dann wird es normal auch schneller, aber selbst dann wird es noch einige Zeit dauern. Da hilft dann nur noch bessere Hardware.
Ich dachte eigentlich immer das kompilierte Python Dateien nur schneller starten jedoch nicht schneller ablaufen (?)
Re: MemoryError lösen
Verfasst: Freitag 31. Dezember 2010, 00:49
von Dauerbaustelle
microkernel hat geschrieben:Py-Prog hat geschrieben:Oder du kompilierst den Code, dann wird es normal auch schneller, aber selbst dann wird es noch einige Zeit dauern. Da hilft dann nur noch bessere Hardware.
Ich dachte eigentlich immer das kompilierte Python Dateien nur schneller starten jedoch nicht schneller ablaufen (?)
Kommt auf die Art der Kompilierung an.
CPython "kompiliert" Python-Programme erst mal zu Bytecode und interpretiert den dann. Der Bytecode für die Datei "foo.py" wird in "foo.pyc" gespeichert. Existiert eine solche Bytecode-Datei bereits bei der Ausführung von "foo.py" und ist sie nicht veraltet, überspringt CPython den Zu-Bytecode-Übersetz-Vorgang und fängt direkt an, den Bytecode zu interpretieren. Deine Annahme war also korrekt.
Es ist allerdings auch möglich, Python nach C zu übersetzen (Cython) oder nach C++ (Shedskin) oder nach JVM-Bytecode (Jython) oder nach .NET-Bytecode (IronPython) oder mit PyPy zur Laufzeit zu kompilieren (mit dem JIT) usf. Zumindest bei Cython, Shedskin und PyPy ist die Chance hoch, dass der Code dann schneller abläuft, weil bei der Kompilierung natürlich Optimierungen gemacht werden können, die CPython nicht macht.
Das tut aber alles überhaupt nichts zur Sache, weil ``hashlib`` sowieso schon in C geschrieben und der Flaschenhals eh die Festplatte ist, wie lunar bereits angemerkt hat.
Re: MemoryError lösen
Verfasst: Freitag 31. Dezember 2010, 11:19
von cofi
microkernel hat geschrieben:Mir stehen nur SHA256, SHA1 und MD5 Hashsummen zum vergleichen zur Verfügung.
Die einfachste Moeglichkeit schneller zu sein, ist es weniger zu machen .. warum also 3 Hashes berechnen?
In dem Fall könnte es aber natuerlich keinen grossen Einfluss haben. Erzaehl uns doch ein wenig mehr ueber das Ziel und die Beschraenkungen unter denen du arbeiten musst.
Re: MemoryError lösen
Verfasst: Samstag 1. Januar 2011, 17:08
von Py-Prog
Ich weiß nicht ob es bei Linux oder Mac geht aber bei Windows kann man über den Taskmanager die Priorität eines Prozesses einstellen das geht auch mit einem Batch-skript. (Wenn das Konsolen Fenster stört mit dem Bat_to_Exe_Converter unsichtbar machen.)