601 Stimmen

Wie liest man eine große Datei - Zeile für Zeile?

Ich möchte jede Zeile einer ganzen Datei durchlaufen. Eine Möglichkeit, dies zu tun, besteht darin, die gesamte Datei zu lesen, sie in einer Liste zu speichern und dann die betreffende Zeile zu durchlaufen. Diese Methode verbraucht viel Speicherplatz, daher suche ich nach einer Alternative.

Mein bisheriger Code:

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)

Das Ausführen dieses Codes führt zu einer Fehlermeldung: device active .

Irgendwelche Vorschläge?

Der Zweck ist die Berechnung der paarweisen String-Ähnlichkeit, d.h. für jede Zeile in der Datei möchte ich den Levenshtein-Abstand zu jeder anderen Zeile berechnen.

5voto

cfi Punkte 10332

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

Ihr Algorithmus liest jedoch die gesamte Datei für jede Zeile der Datei. Das bedeutet, dass der Gesamtaufwand für das Lesen einer Datei - und das Berechnen der Levenshtein-Abstand - wird N*N durchgeführt, wenn N die Anzahl der Zeilen in der Datei ist. Da Sie um die Dateigröße besorgt sind und die Datei nicht im Speicher behalten wollen, bin ich besorgt über die resultierende quadratische Laufzeit . Ihr Algorithmus gehört zur Klasse der O(n^2)-Algorithmen, die oft durch Spezialisierung verbessert werden können.

Ich vermute, dass Sie den Kompromiss zwischen Speicher und Laufzeit bereits kennen, aber vielleicht möchten Sie untersuchen, ob es eine effiziente Möglichkeit gibt, mehrere Levenshtein-Distanzen 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 Prozessorleistung) muss Ihr Algorithmus laufen, und wie hoch ist die tolerierte Laufzeit?

Der Code würde wie folgt aussehen:

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)

Es stellt sich jedoch die Frage, wie man die Entfernungen speichert (Matrix?) und ob es von Vorteil ist, z. B. die outer_line für die Verarbeitung vorzubereiten oder einige Zwischenergebnisse zur Wiederverwendung zu speichern.

3voto

Samuel Dauzon Punkte 9838

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

Ich habe ein Skript erstellt, mit dem ich mehrmals täglich eine Apache access.log-Datei ausschneide. Ich musste also Positionierung des Cursors auf die zuletzt geparste Zeile bei der letzten Ausführung . Zu diesem Zweck habe ich file.seek() y file.seek() Methoden, die die Speicherung 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()))

2voto

KevinDTimm Punkte 14006

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

Dies durchläuft die Zeilen aller Dateien, die in sys.argv[1:] und zwar standardmäßig auf sys.stdin wenn die Liste leer ist

weiter, die Definition der Funktion ist:

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

Wenn ich zwischen den Zeilen lese, sagt mir das, dass files kann eine Liste sein, so dass Sie etwas haben könnten wie:

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

Ver aquí für weitere Informationen

2voto

John Haberstroh Punkte 430

Ich würde dringend davon abraten, das standardmäßige Laden von Dateien zu verwenden, da es entsetzlich langsam ist. Sie sollten sich mit den Numpy-Funktionen und den IOpro-Funktionen (z. B. numpy.loadtxt()) befassen.

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

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

Dann können Sie Ihre paarweisen Operationen in Teile zerlegen:

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 Paketen zu laden und dann Matrixoperationen darauf durchzuführen, als dies Element für Element zu tun!!!

2voto

karlzafiris Punkte 2883
#Using a text file for the example
with open("yourFile.txt","r") as f:
    text = f.readlines()
for line in text:
    print line
  • Öffnen Sie Ihre Datei zum Lesen (r)
  • Lesen Sie die gesamte Datei und speichern Sie jede Zeile in einer Liste (Text)
  • Schleife durch die Liste, um jede Zeile zu drucken.

Wenn Sie z. B. eine bestimmte Zeile auf eine Länge größer als 10 prüfen wollen, arbeiten Sie mit dem, was Sie bereits zur Verfügung haben.

for line in text:
    if len(line) > 10:
        print line

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X