[Sortierung zusammenführen]: https://ja.wikipedia.org/wiki/%E3%83%9E%E3%83%BC%E3%82%B8%E3%82%BD%E3%83%BC%E3% 83% 88 [io.IOBase.readlines]:http://docs.python.jp/3/library/io.html#io.IOBase.readlines
Textdateien müssen in Python-Skripten sortiert werden, die in einer Windows-Umgebung ausgeführt werden.
Die Anforderungen sind wie folgt.
Die Windows-Eingabeaufforderung verfügt über einen [Sortierbefehl] [Windows-Sortierung], der das Sortieren großer Dateien unterstützt. Im Gegensatz zu [Linux sort command] und linux-sort können Sie jedoch kein Trennzeichen (-t) oder keine Sortierung als Zahl (-n) angeben.
Wenn die Größe klein ist, können Sie alle Daten mit einem Python-Skript in den Speicher laden und die Funktion [sortiert] aufrufen. Wenn die Größe jedoch groß ist, geht Ihnen möglicherweise der Speicher aus.
Ich konnte nicht anders, also entschied ich mich, die Sortierverarbeitung für große Dateien in Python zu implementieren.
Verwenden Sie das folgende Konzept von [Sortierung zusammenführen] wie folgt, um eine große Datenmenge zu sortieren.
Ich habe eine Folie [Verarbeitungsverfahren] erstellt, damit Sie sehen können, wie es funktioniert.
Verwenden Sie [io.IOBase.readlines], um die Datei zu teilen und zu lesen.
Wenn Sie Readlines ohne Argumente verwenden, werden alle Zeilen in den Speicher geladen. Die Verwendung von Readlines für große Dateien wird daher als Anti-Pattern bezeichnet.
Readlines können jedoch die Anzahl der Bytes / Zeichen begrenzen, die vom Argument gelesen werden sollen, sodass selbst eine große Textdatei separat gelesen werden kann.
>>> from io import StringIO
>>> f = StringIO("11\n22\n3\n4\n5\n666666\n")
>>> f.readlines(5)
['11\n', '22\n']
>>> f.readlines(5)
['3\n', '4\n', '5\n']
>>> f.readlines(5)
['666666\n']
>>> f.readlines(5)
[]
Es scheint die Anzahl der Bytes für Dateien zu sein, die im Binärmodus geöffnet wurden, und die Anzahl der Zeichen für den Textmodus.
Verwenden Sie heapq.merge zum Zusammenführen. heapq.merge gibt das Ergebnis der Zusammenführung mehrerer sortierter Iterables zurück.
>>> import heapq
>>> list(heapq.merge([1, 3, 4, 7], [2, 5], [6]))
[1, 2, 3, 4, 5, 6, 7]
Es ist in gist aufgeführt. Die Python-Version ist 3.6.
Das Folgende ist ein Auszug aus dem Sortierteil.
import heapq
import os
from contextlib import contextmanager
from operator import itemgetter
from tempfile import TemporaryDirectory, mktemp
from typing import IO, Callable, List
def large_sort(input_file: IO, output_file: IO, key: Callable=None, reverse: bool=False, limit_chars: int=1024*1024*64):
with TemporaryDirectory() as tmp_dir:
for lines in _read_parts(input_file, limit_chars):
lines = sorted(lines, key=key, reverse=reverse)
_write_part(lines, tmp_dir)
with _open_tmp_files(tmp_dir) as tmp_files:
for row in heapq.merge(*tmp_files, key=key, reverse=reverse):
output_file.write(row)
def _read_parts(input_file, limit_chars):
lines = input_file.readlines(limit_chars)
while lines:
yield lines
lines = input_file.readlines(limit_chars)
def _write_part(lines, tmp_dir):
tmp_filename = mktemp(dir=tmp_dir)
with open(tmp_filename, "w") as tmp_file:
tmp_file.writelines(lines)
return tmp_filename
@contextmanager
def _open_tmp_files(tmp_dir):
filenames = os.listdir(tmp_dir)
files = [open(os.path.join(tmp_dir, filename), "r") for filename in filenames]
try:
yield files
finally:
for file in files:
file.close()
In dieser Anforderung wollte ich, dass eine Funktion von einem anderen Python-Skript aufgerufen wird, daher brauche ich sie nicht, aber in der Hauptquelle habe ich sie über die Befehlszeile verfügbar gemacht, indem ich auf den sort-Befehl von Linux verwiesen habe.
Ich habe es dieses Mal selbst gemacht, aber ich werde es schreiben, weil es andere Lösungen gibt.
Recommended Posts