Seite 1 von 1
Speicherverbrauch
Verfasst: Freitag 26. November 2010, 21:05
von ravenheart
Es geht um das gleich vorwegzunehmen immer noch darum, dass ich csv-artige Dateien bearbeiten möchte.
Ich spiele mit dem Gedanken, diese einfach komplett als String einzulesen und eventuell dann zeilenweise(wenn es geht) zu bearbeiten.
Ich hab mal folgendes getestet:
Code: Alles auswählen
f = open("hello.txt")
s = f.read()
s = s.split("\n")
i = 0
for line in s:
print line
f.close()
hello.txt hab ich variabel erzeugt
Code: Alles auswählen
Größe von hello.txt in MB Anzahl an Zeilen(gerundet) Speicherverbrauch in MB (etwa)
30,6 178000 40
166,6 2030000 300
847,7 100000000 6000+ (geht in swap-Bereich)
Kann mir jmd erklären wieso die letzte Dateikonstellation so viel mehr Speicher benötigt?
Re: Speicherverbrauch
Verfasst: Freitag 26. November 2010, 21:20
von jbs
Um den Speicherbedarf zu minimieren, arbeite die Zeilen zeilenweise ab:
Re: Speicherverbrauch
Verfasst: Freitag 26. November 2010, 21:21
von nomnom
ravenheart hat geschrieben:Code: Alles auswählen
f = open("hello.txt")
s = f.read()
s = s.split("\n")
i = 0
for line in s:
print line
f.close()
Ginge einfacher:
Code: Alles auswählen
with open("hello.txt") as f:
s = f.readlines()
for line in s:
print line
Aber zu den Speicherproblemen kann ich nichts sagen. Soll nur ein Hinweis auf `with` und f.readlines() sein.
Re: Speicherverbrauch
Verfasst: Freitag 26. November 2010, 21:55
von schorsch
Ich würde eher zu jbs Version raten
Der Sprung im Speicherverbrauch hängt mit der Zeilenlänge zusammen. Bei den ersten beiden Dateien ist sie recht großzüzgig, bei der letzten hingegen sehr klein. Nun liest du jede Zeile als einzelnen String ein und jedesmal kommt der Basisverbrauch eines Strings hinzu (also das was der String ohne die Zeichen selbst Verbrauch, bei mir 22 Byte, ich weiß nicht ob sich die Implementierungen da unterscheiden), was dann bei der kurzen länge der Strings stärker ins Gewicht fällt, als bei den anderen Dateien. Du kannst ja mal durchrechnen ob das hin kommt.
edit: Mit fällt gerade ein, dass ich irgendwo mal gelesen habe, dass man __sizeof__ nicht trauen kann. Also ist meine Angabe mit vorsicht zu genießen.
Re: Speicherverbrauch
Verfasst: Samstag 27. November 2010, 11:21
von Leonidas
schorsch hat geschrieben:Ich würde eher zu jbs Version raten

Zudem sie auch nicht das obsolete ``readlines`` verwendet, das hier in dem Kontext auch überflüssig ist:
Code: Alles auswählen
with open('hello.txt', 'r') as f:
for line in f:
print line
Re: Speicherverbrauch
Verfasst: Samstag 27. November 2010, 12:51
von sma
Ich tippe darauf, dass die Kapazität der Liste, die bei `split()` entsteht, sprunghaft steigt, etwa in dem sie immer verdoppelt wird. Das kann bei vielen Einträgen dann so einem recht großen Overhead führen. Egal wie viel Speicher ein Rechner nun hat, ich finde es immer besser, Daten stromartig zu verarbeiten, wenn das möglich ist, also die Datei Zeile für Zeile zu lesen. Sollte das CSV-Modul das nicht können, muss man eben schnell selbst jeden String zerhacken.
Code: Alles auswählen
import re
s = "ich, sage, 'Hallo, Welt'"
print([m.group(2) or m.group(1) for m in re.finditer(r"\s*(?:'([^']*)'|([^,]+))", s)])
Stefan
Re: Speicherverbrauch
Verfasst: Samstag 27. November 2010, 14:24
von ravenheart
Ok, ich hab noch ein paar Spielereien gemacht
Code: Alles auswählen
f = open("test.txt")
string = f.read()
strings = string.split("\n")
lines = f.readlines()
Ergebnis von sys.getsizeof():
Wieso verbraucht der string 21 mal so viel Speicher?
Re: Speicherverbrauch
Verfasst: Samstag 27. November 2010, 14:59
von Barabbas
getsizeof() ermittelt nicht die Größe der Objekte, die die Liste referenziert, sondern nur die Größe des Listen-Objekts selbst.
gibt dir zusätzlich die Größe der referenzierten Objekte. Die Liste mit Strings ist hier also größer als ein großer String: Jedes weitere String-Objekt bringt einen Overhead von 24 Byte-32 Byte (Python < 3 und >= 3 unterscheiden sich hier) und die Liste selbst muss natürlich auch noch im Speicher aufbewahrt werden.
Das alles hat aber mit dem Iterieren nichts zu tun: Dabei befindet sich ja nie ein komplettes Abbild der ganzen Datei im Speicher, so dass das die beste Variante für dich sein dürfte.
Besten Gruß,
brb
Re: Speicherverbrauch
Verfasst: Samstag 27. November 2010, 22:50
von snafu
@sma: Wobei man das IMHO noch recht gut mit Pythons String-Methoden hinkriegen kann:
Code: Alles auswählen
>>> [x.strip('\'" ') for x in s.split(',')]
['ich', 'sage', 'Hallo Welt']
Überflüssig zu erwähnen, dass man bei Weiterverwendung der Elemente natürlich besser eine Generator Comprehension verwenden werden sollte.
Re: Speicherverbrauch
Verfasst: Sonntag 28. November 2010, 11:50
von sma
Der reguläre Ausdruck ist so kompliziert, weil ich ein Komma in einem String wie bei 'Hallo, Welt' als ein Element parsen muss. Einfach nur split reicht nämlich gerade nicht. Dummerweise hatte ich das in meinem Beispiel nicht berücksichtigt.
Stefan