In Ihrem aktuellen Code lesen Sie die gesamte Datei gleichzeitig in den Speicher. Da es sich um 500 MB-Dateien handelt, sind das 500 MB-Strings. Und dann wiederholst du sie, was bedeutet, dass Python eine neue 500Mb-Zeichenkette mit der ersten Ersetzung erstellen muss, dann die erste Zeichenkette zerstören, dann eine zweite 500Mb-Zeichenkette für die zweite Ersetzung erstellen und dann die zweite Zeichenkette zerstören muss, und so weiter. für jeden Ersatz. Es stellt sich heraus, dass das Kopieren von Daten hin und her sehr viel ist, ganz zu schweigen von der Verwendung von viel Speicher.
Wenn Sie wissen, dass die Ersetzungen immer in einer Zeile enthalten sein werden, können Sie die Datei Zeile für Zeile lesen, indem Sie darüber iterieren. Python puffert das Lesen, was bedeutet, dass es ziemlich optimiert wird. Sie sollten eine neue Datei unter einem neuen Namen öffnen, um die neue Datei gleichzeitig zu schreiben. Führen Sie den Austausch nacheinander in jeder Zeile durch und schreiben Sie ihn sofort aus.Dadurch wird erheblich die Menge des verwendeten Speichers und die Menge an Speichern hin und her kopiert reduzieren, wie Sie den Ersatz tun:
for file in files:
fname = os.path.join(dir, file)
inFile = codecs.open(fname, "r", "utf-8")
outFile = codecs.open(fname + ".new", "w", "utf-8")
for line in inFile:
newline = do_replacements_on(line)
outFile.write(newline)
inFile.close()
outFile.close()
os.rename(fname + ".new", fname)
Wenn Sie nicht sicher sein können, wenn sie immer auf einer Linie sein werden , die Dinge werden etwas härter; Sie müssten Blöcke manuell unter Verwendung von inFile.read(blocksize)
einlesen und sorgfältig prüfen, ob am Ende der Blockade eine teilweise Übereinstimmung besteht. Nicht so einfach zu machen, aber in der Regel lohnt es sich immer noch die 500Mb Saiten zu vermeiden.
Eine weitere große Verbesserung wäre, wenn Sie die Ersetzungen auf einmal durchführen könnten, statt eine ganze Reihe von Ersatz in der Reihenfolge zu versuchen. Es gibt mehrere Möglichkeiten, das zu tun, aber was am besten passt, hängt ganz davon ab, was Sie ersetzen und womit. Um einzelne Zeichen in etwas anderes zu übersetzen, kann die translate
Methode der Unicode-Objekte bequem sein. Sie geben ihm ein dict Mapping Unicode-Codepoints (als ganze Zahlen) auf Unicode-Strings:
>>> u"\xff and \ubd23".translate({0xff: u"255", 0xbd23: u"something else"})
u'255 and something else'
Für Teil (und nicht nur einzelne Zeichen) zu ersetzen, können Sie die re
Modul nutzen könnten. Die re.sub
Funktion (und die sub
Methode kompilierter regexps) können eine aufrufbare nehmen (eine Funktion) als erstes Argument, die dann für jedes Spiel aufgerufen werden:
>>> import re
>>> d = {u'spam': u'spam, ham, spam and eggs', u'eggs': u'saussages'}
>>> p = re.compile("|".join(re.escape(k) for k in d))
>>> def repl(m):
... return d[m.group(0)]
...
>>> p.sub(repl, u"spam, vikings, eggs and vikings")
u'spam, ham, spam and eggs, vikings, saussages and vikings'
Es ist die Python-Konvention, Instanzvariablen mit Kleinbuchstaben zu benennen. Ich würde auch das Wort "Dict" durch etwas anderes als den Typ ersetzen, um zukünftige Verwirrung zu vermeiden. –
Besteht Ihr Wörterbuchschlüssel aus genau einem chinesischen Zeichen, oder sind mehrere Zeichen pro Schlüssel möglich? Warum möchten Sie chinesische Zeichen durch Ganzzahlen ersetzen? –
@John: Ich habe noch 35 Dateien, die diese Information bereits mit ganzen Zahlen codiert haben, und ich werde meine Analyse in Stata machen, die nicht Unicode liest. Ich muss mehrere Zeichen gleichzeitig lesen, nicht nur 1. – rallen