Wie lese ich eine große Datei - Zeile für Zeile?

536

Ich möchte über jede Zeile einer gesamten Datei iterieren. Eine Möglichkeit, dies zu tun, besteht darin, die gesamte Datei zu lesen, sie in einer Liste zu speichern und dann die interessierende Zeile zu überschreiten. Diese Methode verbraucht viel Speicher, daher suche ich nach einer Alternative.

Mein Code bisher:

for each_line in fileinput.input(input_file):
    do_something(each_line)

    for each_line_again in fileinput.input(input_file):
        do_something(each_line_again)

Die Ausführung dieses Codes gibt eine Fehlermeldung aus : device active.

Irgendwelche Vorschläge?

Der Zweck besteht darin, die paarweise Zeichenfolgenähnlichkeit zu berechnen, dh für jede Zeile in der Datei möchte ich den Levenshtein-Abstand mit jeder anderen Zeile berechnen.

384X21
quelle
4
Warum müssen Sie die gesamte Datei für jede Zeile erneut lesen? Wenn Sie jemandem sagen, was Sie erreichen möchten, können Sie möglicherweise einen besseren Ansatz vorschlagen.
JJJ

Antworten:

1269

Die richtige, vollständig pythonische Methode zum Lesen einer Datei ist die folgende:

with open(...) as f:
    for line in f:
        # Do something with 'line'

Die withAnweisung behandelt das Öffnen und Schließen der Datei, auch wenn im inneren Block eine Ausnahme ausgelöst wird. Das for line in fbehandelt das fDateiobjekt als iterierbar, das automatisch gepufferte E / A- und Speicherverwaltung verwendet, sodass Sie sich nicht um große Dateien kümmern müssen.

Es sollte einen - und vorzugsweise nur einen - offensichtlichen Weg geben, dies zu tun.

Katriel
quelle
14
Ja, dies ist die beste Version mit Python 2.6 und höher
Simon Bergot
3
Ich persönlich bevorzuge Generatoren und Coroutinen für den Umgang mit Datenpipelines.
Jldupont
4
Was wäre die beste Strategie, wenn eine Datei eine riesige Textdatei ist, aber mit einer Zeile und der Idee, Wörter zu verarbeiten?
Mfcabrera
4
Könnte jemand erklären, wie for line in f:es funktioniert? Ich meine, wie ist das Iterieren über ein Dateiobjekt möglich?
Haccks
11
Wenn Sie über ein Objekt iterieren, sucht Python in der Liste der Objektmethoden nach einer speziellen Methode __iter__, die angibt, was zu tun ist. Dateiobjekte definieren diese spezielle Methode, um einen Iterator über die Zeilen zurückzugeben. (Ungefähr.)
Katriel
130

Zwei speichereffiziente Methoden in Rangfolge (die erste ist die beste) -

  1. Verwendung von with- unterstützt von Python 2.5 und höher
  2. Verwendung von, yieldwenn Sie wirklich die Kontrolle darüber haben möchten, wie viel gelesen werden soll

1. Verwendung von with

withist die schöne und effiziente pythonische Art, große Dateien zu lesen. Vorteile - 1) Das Dateiobjekt wird nach dem Verlassen des withAusführungsblocks automatisch geschlossen . 2) Ausnahmebehandlung innerhalb des withBlocks. 3) Die Speicherschleife fordurchläuft das Dateiobjekt fzeilenweise. Intern werden gepufferte E / A-Vorgänge (zur Optimierung kostspieliger E / A-Vorgänge) und Speicherverwaltung ausgeführt.

with open("x.txt") as f:
    for line in f:
        do something with data

2. Verwendung von yield

Manchmal möchte man eine genauere Kontrolle darüber, wie viel in jeder Iteration gelesen werden soll. Verwenden Sie in diesem Fall iter & ield . Beachten Sie, dass bei dieser Methode die Datei am Ende explizit geschlossen werden muss.

def readInChunks(fileObj, chunkSize=2048):
    """
    Lazy function to read a file piece by piece.
    Default chunk size: 2kB.
    """
    while True:
        data = fileObj.read(chunkSize)
        if not data:
            break
        yield data

f = open('bigFile')
for chuck in readInChunks(f):
    do_something(chunk)
f.close()

Fallstricke und der Vollständigkeit halber - Die folgenden Methoden sind nicht so gut oder nicht so elegant zum Lesen großer Dateien, aber bitte lesen Sie sie, um ein umfassendes Verständnis zu erhalten.

In Python besteht die häufigste Methode zum Lesen von Zeilen aus einer Datei darin, Folgendes zu tun:

for line in open('myfile','r').readlines():
    do_something(line)

Wenn dies erledigt ist, lädt die readlines()Funktion (dasselbe gilt für die read()Funktion) die gesamte Datei in den Speicher und iteriert dann darüber. Ein etwas besserer Ansatz (die beiden erstgenannten Methoden sind die besten) für große Dateien ist die Verwendung des fileinputModuls wie folgt:

import fileinput

for line in fileinput.input(['myfile']):
    do_something(line)

Der fileinput.input()Aufruf liest Zeilen nacheinander, speichert sie jedoch nicht im Speicher, nachdem sie gelesen wurden, oder auch nur so, da filein Python iterierbar ist.

Verweise

  1. Python mit Anweisung
Srikar Appalaraju
quelle
9
-1 Es ist im Grunde nie eine gute Idee for line in open(...).readlines(): <do stuff>. Warum würdest du?! Sie haben gerade alle Vorteile von Pythons cleverem gepufferten Iterator-E / A ohne Nutzen verloren.
Katriel
5
@Srikar: Es gibt eine Zeit und einen Ort, um alle möglichen Lösungen für ein Problem zu finden. Einem Anfänger beizubringen, wie man Dateien eingibt, ist es nicht. Die richtige Antwort am Ende eines langen Beitrags voller falscher Antworten zu haben, ist kein guter Unterricht.
Katriel
6
@Srikar: Sie könnten Ihren Beitrag deutlich verbessern, indem Sie den richtigen Weg nach oben setzen, dann erwähnen readlinesund erklären, warum dies nicht gut ist (weil die Datei in den Speicher eingelesen wird) und dann erklären, was das fileinputModul tut und warum Sie Vielleicht möchten Sie es gegenüber den anderen Methoden verwenden, dann erklären, wie das Chunking der Datei die E / A verbessert, und ein Beispiel für die Chunking-Funktion geben (aber erwähnen, dass Python dies bereits für Sie erledigt, damit Sie es nicht müssen). Es ist jedoch nicht gut, nur fünf Möglichkeiten zur Lösung eines einfachen Problems anzugeben, von denen vier in diesem Fall falsch sind.
Katriel
2
Was auch immer Sie der Vollständigkeit halber hinzufügen, fügen Sie es zuletzt und nicht zuerst hinzu. Zeigen Sie zuerst den richtigen Weg.
M000
6
@katrielalex hat meine Antwort erneut überprüft und festgestellt, dass eine Umstrukturierung erforderlich ist. Ich kann sehen, wie die frühere Antwort Verwirrung stiften kann. Hoffentlich würde dies für zukünftige Benutzer klar machen.
Srikar Appalaraju
37

So entfernen Sie Zeilenumbrüche:

with open(file_path, 'rU') as f:
    for line_terminated in f:
        line = line_terminated.rstrip('\n')
        ...

Mit Universal-Newline - Unterstützung alle Textdatei Linien scheinen beendet zu werden '\n', was auch immer die Terminatoren in der Datei '\r', '\n'oder '\r\n'.

BEARBEITEN - So legen Sie die universelle Newline-Unterstützung fest:

  • Python 2 unter Unix - open(file_path, mode='rU')- erforderlich [danke @ Dave ]
  • Python 2 unter Windows - open(file_path, mode='rU')- optional
  • Python 3 - open(file_path, newline=None)- optional

Der newlineParameter wird nur in Python 3 unterstützt und ist standardmäßig auf None. Der modeParameter ist 'r'in allen Fällen standardmäßig . Das Uist in Python veraltet 3. In Python 2 unter Windows einen anderen Mechanismus zu übersetzen scheint \r\nzu \n.

Docs:

So behalten Sie native Zeilenabschlüsse bei:

with open(file_path, 'rb') as f:
    with line_native_terminated in f:
        ...

Der Binärmodus kann die Datei weiterhin in Zeilen mit analysieren in. Jede Zeile enthält alle Terminatoren in der Datei.

Dank @katrielalex ‚s Antwort , Pythons open () doc, und ipython Experimente.

Bob Stein
quelle
1
Auf Python 2.7 musste ich open(file_path, 'rU')universelle Zeilenumbrüche aktivieren.
Dave
17

Dies ist eine Möglichkeit, eine Datei in Python zu lesen:

f = open(input_file)
for line in f:
    do_stuff(line)
f.close()

Es wird keine vollständige Liste zugewiesen. Es iteriert über die Zeilen.

Simon Bergot
quelle
2
Während dies funktioniert, ist es definitiv nicht der kanonische Weg. Der kanonische Weg ist die Verwendung eines Kontext-Wrappers wie with open(input_file) as f:. Dies erspart Ihnen das f.close()und stellt sicher, dass Sie nicht versehentlich vergessen, es zu schließen. Verhindert Speicherlecks und alles, was beim Lesen von Dateien sehr wichtig ist.
Mast
1
Wie @Mast sagte, ist das nicht der kanonische Weg, also stimmen Sie dafür ab.
Azuax
12

Ein Zusammenhang im Vorfeld, woher ich komme. Code-Schnipsel sind am Ende.

Wenn ich kann, bevorzuge ich die Verwendung eines Open-Source-Tools wie H2O, um parallele CSV-Dateilesevorgänge mit hoher Leistung durchzuführen. Dieses Tool ist jedoch in seinen Funktionen eingeschränkt. Am Ende schreibe ich viel Code, um Data Science-Pipelines zu erstellen, bevor ich sie für das überwachte Lernen in den H2O-Cluster einspeise.

Ich habe Dateien wie 8 GB HIGGS-Dataset von UCI Repo und sogar 40 GB CSV-Dateien für datenwissenschaftliche Zwecke erheblich schneller gelesen, indem ich viel Parallelität mit dem Poolobjekt und der Kartenfunktion der Multiprozessor-Bibliothek hinzugefügt habe. Zum Beispiel erfordert das Clustering mit Suchvorgängen für den nächsten Nachbarn sowie DBSCAN- und Markov-Clustering-Algorithmen einige parallele Programmierfinesse, um einige ernsthaft herausfordernde Speicher- und Wanduhrzeitprobleme zu umgehen.

Normalerweise teile ich die Datei gerne zeilenweise mit Gnu-Tools in Teile auf und maskiere sie dann alle, um sie parallel im Python-Programm zu finden und zu lesen. Ich verwende üblicherweise mehr als 1000 Teildateien. Das Ausführen dieser Tricks hilft immens bei der Verarbeitungsgeschwindigkeit und den Speicherbeschränkungen.

Der pandas dataframe.read_csv ist ein Single-Thread, sodass Sie diese Tricks ausführen können, um Pandas schneller zu machen, indem Sie eine map () für die parallele Ausführung ausführen. Sie können htop verwenden, um zu sehen, dass bei einfachen alten sequentiellen Pandas dataframe.read_csv 100% CPU auf nur einem Kern der eigentliche Engpass in pd.read_csv ist, nicht auf der Festplatte.

Ich sollte hinzufügen, dass ich eine SSD auf einem schnellen Grafikkartenbus verwende, keine sich drehende HD auf einem SATA6-Bus sowie 16 CPU-Kerne.

Eine andere Technik, von der ich herausgefunden habe, dass sie in einigen Anwendungen hervorragend funktioniert, ist das parallele Lesen von CSV-Dateien innerhalb einer riesigen Datei, wobei jeder Worker mit einem unterschiedlichen Versatz in die Datei gestartet wird, anstatt eine große Datei in viele Teiledateien vorab aufzuteilen. Verwenden Sie Pythons Dateisuche () und tell () in jedem parallelen Worker, um die große Textdatei in Streifen an verschiedenen Start- und Endbytepositionen des Byteversatzes in der großen Datei gleichzeitig zu lesen. Sie können eine Regex-Suche für die Bytes durchführen und die Anzahl der Zeilenvorschübe zurückgeben. Dies ist eine Teilsumme. Summieren Sie schließlich die Teilsummen, um die globale Summe zu erhalten, wenn die Kartenfunktion nach Beendigung der Arbeit zurückkehrt.

Im Folgenden finden Sie einige Beispielbenchmarks, die den Parallel-Byte-Offset-Trick verwenden:

Ich benutze 2 Dateien: HIGGS.csv ist 8 GB. Es stammt aus dem UCI-Repository für maschinelles Lernen. all_bin .csv ist 40,4 GB groß und stammt aus meinem aktuellen Projekt. Ich benutze 2 Programme: das mit Linux gelieferte GNU wc-Programm und das von mir entwickelte reine Python fastread.py-Programm.

HP-Z820:/mnt/fastssd/fast_file_reader$ ls -l /mnt/fastssd/nzv/HIGGS.csv
-rw-rw-r-- 1 8035497980 Jan 24 16:00 /mnt/fastssd/nzv/HIGGS.csv

HP-Z820:/mnt/fastssd$ ls -l all_bin.csv
-rw-rw-r-- 1 40412077758 Feb  2 09:00 all_bin.csv

ga@ga-HP-Z820:/mnt/fastssd$ time python fastread.py --fileName="all_bin.csv" --numProcesses=32 --balanceFactor=2
2367496

real    0m8.920s
user    1m30.056s
sys 2m38.744s

In [1]: 40412077758. / 8.92
Out[1]: 4530501990.807175

Das sind etwa 4,5 GB / s oder 45 Gbit / s, die Geschwindigkeit beim Schlürfen von Dateien. Das ist keine sich drehende Festplatte, mein Freund. Das ist eigentlich eine Samsung Pro 950 SSD.

Unten finden Sie den Geschwindigkeits-Benchmark für dieselbe Datei, die von gnu wc, einem reinen C-kompilierten Programm, zeilenweise gezählt wird.

Was cool ist, ist, dass mein reines Python-Programm in diesem Fall im Wesentlichen der Geschwindigkeit des von gnu wc kompilierten C-Programms entspricht. Python wird interpretiert, aber C wird kompiliert, daher ist dies eine ziemlich interessante Leistung, ich denke, Sie würden dem zustimmen. Natürlich muss wc wirklich in ein paralleles Programm geändert werden, und dann würde es wirklich die Socken von meinem Python-Programm schlagen. Aber so wie es heute ist, ist gnu wc nur ein sequentielles Programm. Sie tun, was Sie können, und Python kann heute parallel tun. Das Kompilieren von Cython kann mir möglicherweise helfen (für eine andere Zeit). Auch Speicherzuordnungsdateien wurden noch nicht untersucht.

HP-Z820:/mnt/fastssd$ time wc -l all_bin.csv
2367496 all_bin.csv

real    0m8.807s
user    0m1.168s
sys 0m7.636s


HP-Z820:/mnt/fastssd/fast_file_reader$ time python fastread.py --fileName="HIGGS.csv" --numProcesses=16 --balanceFactor=2
11000000

real    0m2.257s
user    0m12.088s
sys 0m20.512s

HP-Z820:/mnt/fastssd/fast_file_reader$ time wc -l HIGGS.csv
11000000 HIGGS.csv

real    0m1.820s
user    0m0.364s
sys 0m1.456s

Fazit: Die Geschwindigkeit ist für ein reines Python-Programm im Vergleich zu einem C-Programm gut. Es ist jedoch nicht gut genug, das reine Python-Programm über dem C-Programm zu verwenden, zumindest nicht für die Zählung. Im Allgemeinen kann die Technik für andere Dateiverarbeitungen verwendet werden, sodass dieser Python-Code immer noch gut ist.

Frage: Verbessert das einmalige Kompilieren des regulären Ausdrucks und das Weitergeben an alle Mitarbeiter die Geschwindigkeit? Antwort: Die Vorkompilierung von Regex hilft in dieser Anwendung NICHT. Ich nehme an, der Grund dafür ist, dass der Aufwand für die Serialisierung und Erstellung von Prozessen für alle Mitarbeiter dominiert.

Eine Sache noch. Hilft das parallele Lesen von CSV-Dateien überhaupt? Ist die Festplatte der Engpass oder die CPU? Viele sogenannte Top-Antworten auf Stackoverflow enthalten die allgemeine Entwickler-Weisheit, dass Sie nur einen Thread benötigen, um eine Datei zu lesen. Das Beste, was Sie tun können, heißt es. Sind sie sich aber sicher?

Lass es uns herausfinden:

HP-Z820:/mnt/fastssd/fast_file_reader$ time python fastread.py --fileName="HIGGS.csv" --numProcesses=16 --balanceFactor=2
11000000

real    0m2.256s
user    0m10.696s
sys 0m19.952s

HP-Z820:/mnt/fastssd/fast_file_reader$ time python fastread.py --fileName="HIGGS.csv" --numProcesses=1 --balanceFactor=1
11000000

real    0m17.380s
user    0m11.124s
sys 0m6.272s

Oh ja, ja, das tut es. Das parallele Lesen von Dateien funktioniert recht gut. Na siehst du!

Ps. Falls einige von Ihnen wissen wollten, was wäre, wenn der balanceFactor bei Verwendung eines einzelnen Worker-Prozesses 2 wäre? Nun, es ist schrecklich:

HP-Z820:/mnt/fastssd/fast_file_reader$ time python fastread.py --fileName="HIGGS.csv" --numProcesses=1 --balanceFactor=2
11000000

real    1m37.077s
user    0m12.432s
sys 1m24.700s

Wichtige Teile des Python-Programms fastread.py:

fileBytes = stat(fileName).st_size  # Read quickly from OS how many bytes are in a text file
startByte, endByte = PartitionDataToWorkers(workers=numProcesses, items=fileBytes, balanceFactor=balanceFactor)
p = Pool(numProcesses)
partialSum = p.starmap(ReadFileSegment, zip(startByte, endByte, repeat(fileName))) # startByte is already a list. fileName is made into a same-length list of duplicates values.
globalSum = sum(partialSum)
print(globalSum)


def ReadFileSegment(startByte, endByte, fileName, searchChar='\n'):  # counts number of searchChar appearing in the byte range
    with open(fileName, 'r') as f:
        f.seek(startByte-1)  # seek is initially at byte 0 and then moves forward the specified amount, so seek(5) points at the 6th byte.
        bytes = f.read(endByte - startByte + 1)
        cnt = len(re.findall(searchChar, bytes)) # findall with implicit compiling runs just as fast here as re.compile once + re.finditer many times.
    return cnt

Die Definition für PartitionDataToWorkers ist nur gewöhnlicher sequentieller Code. Ich habe es weggelassen, falls jemand anderes etwas üben möchte, wie paralleles Programmieren ist. Ich habe die schwierigeren Teile kostenlos verschenkt: den getesteten und funktionierenden Parallelcode, zu Ihrem Lernvorteil.

Dank an: Das Open-Source-H2O-Projekt von Arno und Cliff und den H2O-Mitarbeitern für ihre großartige Software und Lehrvideos, die mich wie oben gezeigt zu diesem reinen Python-Hochleistungs-Parallelbyte-Offset-Lesegerät inspiriert haben. H2O liest parallel Dateien mit Java, kann von Python- und R-Programmen aufgerufen werden und ist verrückt schnell und schneller als alles andere auf der Welt beim Lesen großer CSV-Dateien.

Geoffrey Anderson
quelle
Parallele Chunks sind im Grunde genommen das, was dies ist. Ich gehe auch davon aus, dass SSD und Flash die einzigen kompatiblen Speichergeräte mit dieser Technik sind. Es ist unwahrscheinlich, dass sich HD dreht.
Geoffrey Anderson
1
Wie haben Sie die Caching-Datenträgerdateien des Betriebssystems berücksichtigt?
JamesThomasMoon1979
5

Katrielalex bot die Möglichkeit, eine Datei zu öffnen und zu lesen.

Wie auch immer Ihr Algorithmus vorgeht, er liest die gesamte Datei für jede Zeile der Datei. Das bedeutet, dass die Gesamtmenge des Lesens einer Datei - und des Berechnens der Levenshtein-Entfernung - N * N erfolgt, wenn N die Anzahl der Zeilen in der Datei ist. Da Sie sich Sorgen um die Dateigröße machen und diese nicht im Speicher behalten möchten, mache ich mir Sorgen um die resultierende quadratische Laufzeit . Ihr Algorithmus gehört zur Klasse der O (n ^ 2) -Algorithmen, die häufig durch Spezialisierung verbessert werden können.

Ich vermute, dass Sie hier bereits den Kompromiss zwischen Speicher und Laufzeit kennen, aber vielleicht möchten Sie untersuchen, ob es eine effiziente Möglichkeit gibt, mehrere Levenshtein-Entfernungen parallel zu berechnen. Wenn ja, wäre es interessant, Ihre Lösung hier zu teilen.

Wie viele Zeilen haben Ihre Dateien und auf welcher Art von Maschine (Speicher- und CPU-Leistung) muss Ihr Algorithmus ausgeführt werden, und wie hoch ist die tolerierte Laufzeit?

Code würde aussehen wie:

with f_outer as open(input_file, 'r'):
    for line_outer in f_outer:
        with f_inner as open(input_file, 'r'):
            for line_inner in f_inner:
                compute_distance(line_outer, line_inner)

Die Fragen sind jedoch, wie Sie die Abstände speichern (Matrix?) Und ob Sie einen Vorteil daraus ziehen können, z. B. die äußere Zeile für die Verarbeitung vorzubereiten oder einige Zwischenergebnisse für die Wiederverwendung zwischenzuspeichern.

cfi
quelle
Mein Punkt ist, dass dieser Beitrag keine Antwort auf die Frage enthält, nur noch ein paar Fragen! IMO wäre es besser als Kommentar geeignet.
Katriel
1
@katriealex: Err. Seltsam. Sie haben die verschachtelten Schleifen gesehen und Ihre eigene Antwort erweitert, um sie an die eigentliche Frage anzupassen? Ich kann meine Fragen hier aus meiner Antwort entfernen, und es gibt noch genügend Inhalte, um dies als - wenn auch teilweise - Antwort zu rechtfertigen. Ich könnte auch akzeptieren, wenn Sie Ihre eigene Antwort so bearbeiten würden, dass sie das Beispiel einer verschachtelten Schleife enthält, das von der Frage explizit gestellt wurde, und dann kann ich meine eigene Antwort glücklich entfernen. Aber eine Abwertung bekomme ich überhaupt nicht.
cfi
Meinetwegen; Ich sehe das Demonstrieren der verschachtelten for-Schleifen nicht wirklich als Antwort auf die Frage, aber ich denke, es richtet sich ziemlich stark an Anfänger. Downvote entfernt.
Katriel
3
#Using a text file for the example
with open("yourFile.txt","r") as f:
    text = f.readlines()
for line in text:
    print line
  • Öffne deine Datei zum Lesen (r)
  • Lesen Sie die gesamte Datei und speichern Sie jede Zeile in einer Liste (Text).
  • Durchlaufen Sie die Liste und drucken Sie jede Zeile.

Wenn Sie beispielsweise eine bestimmte Zeile auf eine Länge von mehr als 10 prüfen möchten, arbeiten Sie mit dem, was Sie bereits zur Verfügung haben.

for line in text:
    if len(line) > 10:
        print line
Atlas
quelle
1
Nicht das Beste für diese Frage, aber dieser Code ist hauptsächlich nützlich, wenn das, wonach Sie suchen, "schlürft" (die gesamte Datei auf einmal liest). Das war mein Fall und Google hat mich hierher gebracht. +1. Aus Gründen der Atomizität oder wenn Sie eine zeitaufwändige Verarbeitung in der Schleife durchführen, kann das Lesen der gesamten Datei möglicherweise schneller erfolgen
ntg
1
Außerdem wurde der Code ein wenig verbessert: 1. Schließen ist nicht erforderlich, nachdem: ( docs.python.org/2/tutorial/inputoutput.html , nach "Es wird empfohlen , das Schlüsselwort with zu verwenden ...") 2 . Text kann verarbeitet werden, nachdem die Datei gelesen wurde (außerhalb der Schleife ....)
ntg
2

Aus der Python-Dokumentation für fileinput .input ():

Dies durchläuft die Zeilen aller in aufgelisteten Dateien sys.argv[1:], standardmäßig, sys.stdinwenn die Liste leer ist

Ferner lautet die Definition der Funktion:

fileinput.FileInput([files[, inplace[, backup[, mode[, openhook]]]]])

Wenn ich zwischen den Zeilen lese, weiß ich, dass es filessich um eine Liste handeln kann, damit Sie so etwas wie Folgendes haben können:

for each_line in fileinput.input([input_file, input_file]):
  do_something(each_line)

Sehen Sie hier für weitere Informationen

KevinDTimm
quelle
2

Ich würde dringend empfehlen, das Standard-Laden von Dateien nicht zu verwenden, da es schrecklich langsam ist. Sie sollten sich die numpy-Funktionen und die IOpro-Funktionen ansehen (z. B. numpy.loadtxt ()).

http://docs.scipy.org/doc/numpy/user/basics.io.genfromtxt.html

https://store.continuum.io/cshop/iopro/

Dann können Sie Ihre paarweise Operation in Stücke aufteilen:

import numpy as np
import math

lines_total = n    
similarity = np.zeros(n,n)
lines_per_chunk = m
n_chunks = math.ceil(float(n)/m)
for i in xrange(n_chunks):
    for j in xrange(n_chunks):
        chunk_i = (function of your choice to read lines i*lines_per_chunk to (i+1)*lines_per_chunk)
        chunk_j = (function of your choice to read lines j*lines_per_chunk to (j+1)*lines_per_chunk)
        similarity[i*lines_per_chunk:(i+1)*lines_per_chunk,
                   j*lines_per_chunk:(j+1)*lines_per_chunk] = fast_operation(chunk_i, chunk_j) 

Es ist fast immer viel schneller, Daten in Chunks zu laden und dann Matrixoperationen durchzuführen, als sie Element für Element auszuführen !!

John Haberstroh
quelle
0

Müssen Sie häufig eine große Datei von der letzten Positionslesung lesen?

Ich habe ein Skript erstellt, mit dem eine Apache access.log-Datei mehrmals täglich geschnitten wird. Also musste ich einen Positionscursor auf die letzte Zeile setzen, die während der letzten Ausführung analysiert wurde . Zu diesem Zweck habe ich file.seek()und file.seek()Methoden verwendet, die das Speichern des Cursors in einer Datei ermöglichen.

Mein Code:

ENCODING = "utf8"
CURRENT_FILE_DIR = os.path.dirname(os.path.abspath(__file__))

# This file is used to store the last cursor position
cursor_position = os.path.join(CURRENT_FILE_DIR, "access_cursor_position.log")

# Log file with new lines
log_file_to_cut = os.path.join(CURRENT_FILE_DIR, "access.log")
cut_file = os.path.join(CURRENT_FILE_DIR, "cut_access", "cut.log")

# Set in from_line 
from_position = 0
try:
    with open(cursor_position, "r", encoding=ENCODING) as f:
        from_position = int(f.read())
except Exception as e:
    pass

# We read log_file_to_cut to put new lines in cut_file
with open(log_file_to_cut, "r", encoding=ENCODING) as f:
    with open(cut_file, "w", encoding=ENCODING) as fw:
        # We set cursor to the last position used (during last run of script)
        f.seek(from_position)
        for line in f:
            fw.write("%s" % (line))

    # We save the last position of cursor for next usage
    with open(cursor_position, "w", encoding=ENCODING) as fw:
        fw.write(str(f.tell()))
Samuel Dauzon
quelle
-2

Der beste Weg , große Datei, Zeile für Zeile zu lesen ist Python verwenden enumerate Funktion

with open(file_name, "rU") as read_file:
    for i, row in enumerate(read_file, 1):
        #do something
        #i in line of that line
        #row containts all data of that line
Anurag Misra
quelle
3
Warum ist die Verwendung von enumerate besser? Der einzige Vorteil gegenüber der akzeptierten Antwort besteht darin, dass Sie einen Index erhalten, den OP nicht benötigt, und den Code weniger lesbar machen.
Fuyas