Ich benutze Python 2.6 auf einem Mac Mini mit 1 GB RAM. Ich möchte eine große Textdatei einlesenPython: Wie man riesige Textdatei in den Speicher liest
$ ls -l links.csv; file links.csv; tail links.csv
-rw-r--r-- 1 user user 469904280 30 Nov 22:42 links.csv
links.csv: ASCII text, with CRLF line terminators
4757187,59883
4757187,99822
4757187,66546
4757187,638452
4757187,4627959
4757187,312826
4757187,6143
4757187,6141
4757187,3081726
4757187,58197
Also jede Zeile in der Datei besteht aus einem Tupel von zwei durch Kommas getrennten Integer-Werten. Ich möchte die ganze Datei einlesen und nach der zweiten Spalte sortieren. Ich weiß, dass ich die Sortierung durchführen kann, ohne die ganze Datei in den Speicher zu schreiben. Aber ich dachte für eine Datei von 500MB sollte ich noch in der Lage sein, es im Speicher zu tun, da ich 1GB zur Verfügung habe.
Wenn ich jedoch versuche, die Datei einzulesen, scheint Python viel mehr Speicher zuzuweisen, als von der Datei auf der Festplatte benötigt wird. Also selbst mit 1GB RAM kann ich die 500MB Datei nicht in den Speicher einlesen. Mein Python-Code für die Datei zu lesen und drucken einige Informationen über den Speicherverbrauch ist:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
infile=open("links.csv", "r")
edges=[]
count=0
#count the total number of lines in the file
for line in infile:
count=count+1
total=count
print "Total number of lines: ",total
infile.seek(0)
count=0
for line in infile:
edge=tuple(map(int,line.strip().split(",")))
edges.append(edge)
count=count+1
# for every million lines print memory consumption
if count%1000000==0:
print "Position: ", edge
print "Read ",float(count)/float(total)*100,"%."
mem=sys.getsizeof(edges)
for edge in edges:
mem=mem+sys.getsizeof(edge)
for node in edge:
mem=mem+sys.getsizeof(node)
print "Memory (Bytes): ", mem
Der Ausgang ich erhielt, war:
Total number of lines: 30609720
Position: (9745, 2994)
Read 3.26693612356 %.
Memory (Bytes): 64348736
Position: (38857, 103574)
Read 6.53387224712 %.
Memory (Bytes): 128816320
Position: (83609, 63498)
Read 9.80080837067 %.
Memory (Bytes): 192553000
Position: (139692, 1078610)
Read 13.0677444942 %.
Memory (Bytes): 257873392
Position: (205067, 153705)
Read 16.3346806178 %.
Memory (Bytes): 320107588
Position: (283371, 253064)
Read 19.6016167413 %.
Memory (Bytes): 385448716
Position: (354601, 377328)
Read 22.8685528649 %.
Memory (Bytes): 448629828
Position: (441109, 3024112)
Read 26.1354889885 %.
Memory (Bytes): 512208580
Bereits nach nur 25% der 500 MB-Datei zu lesen, Python verbraucht 500 MB. Es scheint also, dass das Speichern des Inhalts der Datei als eine Liste von Tupeln von Ints nicht sehr speichereffizient ist. Gibt es einen besseren Weg, es zu tun, so dass ich meine 500 MB-Datei in meinen 1 GB Speicher einlesen kann?
ich mit Dolmetscher erraten, wie Python, u wissen nicht wirklich, wo der Speicher geht. Listen (normalerweise - ich kenne die genaue Python-Implementierung nicht) benötigen jedoch mehr Speicher als Arrays, zum Beispiel für prev/next-Zeiger. Sie müssen wahrscheinlich C/C++ verwenden, um genau zu wissen, wie viel Speicher Sie verwenden. – Drakosha
Sie basieren Ihre Schätzung auf den Rohdaten, aber dann Tupel und Ints erstellen. Verglichen mit kurzen Strings ist Pythons Instanzen-Overhead hier sichtbar, wie Sie sehen können. Du kannst diese Daten auch als reine Strings sortieren, hast du das probiert? – u0b34a0f6ae
Meine Speicherschätzung addiert den Speicherverbrauch der Ints, der Tupel und der Liste. Es ist ganz in Ordnung, es ist ungefähr dasselbe (minus dem Speicher, den der Python-Interpreter verbraucht) als das, was ich oben benutze. Aber ich habe nicht versucht, die Daten als reine Zeichenfolgen zu sortieren. Wie würde ich das tun? – asmaier