2016-12-21 4 views
2

Ich habe eine große Textdatei (~ 450MB -> 129.000 Zeilen und 457.000.000 Zeichen), wenn ich versuche, mit dieser Datei nach einiger Zeit zu arbeiten, ist Memory Error steigt, hier ist mein Code:Speicherfehler beim Arbeiten mit großen Textkorpus

docDict = {} 
ind = 1 

with open('somefile.txt',encoding='utf-8') as f: 
    for line in f: 
     data = line.split(' ') 
     docDict[ind] = data 
     ind+=1 

ich sah this, aber ich lese Zeile Dateizeile.

Antwort

0

Die memory error erhebt sich hier, denn auch wenn Sie Ihre Datei Zeile für Zeile lesen, speichern Sie ihren Inhalt in Ihrem Wörterbuch docDict, also im Speicher.

Ich weiß nicht, was Sie mit diesem Wörterbuch tun, aber ich empfehle, den Prozess nach jede Zeile Sie lesen, und speichern Sie das Ergebnis in einer Variablen (wenn der Prozess viel komprimiert), oder direkt in einer Datei oder Datenbank.

Ich hoffe, ich half! Tschüss !

1

Um den Overhead der Datenstruktur in Ihrem Code zu testen, schrieb ich das folgende Testprogramm. Es nimmt an, dass Ihre Textdatei N Megabyte in ASCII-Codierung mit relativ kurzen Zeilen war. (Ich hatte N 450-150 zu ändern, nachdem meine physischen Speicher liefen.)

import sys 

MB = 1024 * 1024 

line = "the quick brown fox jumps over the lazy dog" 
megs = 150 
nlines = (megs * MB)/len(line) 

d = {} 
for i in xrange(nlines): 
    d[i] = line.split(' ') 

dict_size = sys.getsizeof(d) 
list_size = sum(sys.getsizeof(a) for a in d.items()) 
item_size = sum(sum(sys.getsizeof(s) for s in a) for a in d.items()) 

print " dict:", dict_size/float(MB), "MB" 
print "lists:", list_size/float(MB), "MB" 
print "items:", item_size/float(MB), "MB" 
print "total:", (dict_size + list_size + item_size)/float(MB), "MB" 

mit dem Ergebnis:

dict: 192.00 MB 
lists: 251.16 MB 
items: 669.77 MB 
total: 1112.9 MB 

den Activity Monitor beobachten, überschreitet der Python-Prozess 2 Gigabyte Speichernutzung , also gibt es auch etwas Speicher, der nicht berücksichtigt wurde. Artefakte der malloc Implementierung könnten eine Möglichkeit sein.

ich das gleiche Programm in C++ implementiert:

#include <string> 
#include <vector> 
#include <unordered_map> 

int main() 
{ 
    int const MB = 1024 * 1024; 

    std::string const line = "the quick brown fox jumps over the lazy dog"; 
    std::vector<std::string> const split = { 
     "the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog" 
    }; 

    int const megs = 150; 
    int const nlines = (megs * MB)/line.size(); 

    std::unordered_map<int, std::vector<std::string>> d; 
    for (int i = 0; i < nlines; ++i) { 
     d[i] = split; 
    } 
} 

mit clang++ -O3 Zusammengestellt, benutzten über 1 GB Arbeitsspeicher. C++ hat nicht sys.getsizeof(), also erfordert es etwas mehr Arbeit, um die Speicherauslastung zu brechen, und ich habe diese Arbeit nicht getan.

Zweimal der Speicher des äquivalenten C++ ist eigentlich ein ziemlich gutes Ergebnis für Python, deshalb entferne ich meine Kommentare vor der Bearbeitung der cPython-Implementierung.

Ich denke, Ihr Hauptproblem besteht darin, die Zeile als ein Array von kurzen Strings zu speichern. Ist es möglich, die Zeilen als ganze Strings zu speichern und nach Bedarf aufzuteilen, aber nicht auf einmal?

Was ist das Endziel Ihres Programms?

+0

Leider hat jede Zeile mindestens 100 Wörter zu 1000 Wörtern !! Wie kann ich meinen Code komplizieren? – Arman

+0

Eigentlich, wenn ich mein Programm auf "line = 10 *" ändere, springt der schnelle braune Fuchs über den faulen Hund "', der Speicherverbrauch sinkt sehr, auch für die 'Items'. Das ist überraschend - ich würde nur erwarten, dass der 'dict'- und' list'-Overhead sinken würde. – japreiss

+0

hinzugefügt einen C++ - Vergleich und neue Schlussfolgerungen, siehe Änderungen. – japreiss

Verwandte Themen