381 Stimmen

Lazy Methode für das Lesen von großen Datei in Python?

Ich habe eine sehr große Datei von 4 GB, und wenn ich versuche, sie zu lesen, bleibt mein Computer hängen. Ich möchte sie also Stück für Stück lesen und nach der Verarbeitung jedes Stücks das verarbeitete Stück in einer anderen Datei speichern und das nächste Stück lesen.

Gibt es eine Methode, um yield diese Stücke ?

Ich hätte gerne eine Faulenzermethode .

14voto

Boris V Punkte 10136

In Python 3.8+ können Sie .read() in einem while Schleife:

with open("somefile.txt") as f:
    while chunk := f.read(8192):
        do_something(chunk)

Natürlich können Sie jede beliebige Stückchengröße verwenden, Sie müssen nicht die 8192 ( 2**13 ) Bytes. Sofern die Größe Ihrer Datei nicht zufällig ein Vielfaches der Chunk-Größe ist, wird der letzte Chunk kleiner sein als die Chunk-Größe.

7voto

bruce Punkte 422

Siehe die offizielle Dokumentation von Python https://docs.python.org/3/library/functions.html#iter

Vielleicht ist diese Methode eher pythonisch:

from functools import partial

"""A file object returned by open() is a iterator with
read method which could specify current read's block size"""
with open('mydata.db', 'r') as f_in:

    part_read = partial(f_in.read, 1024*1024)
    iterator = iter(part_read, b'')

    for index, block in enumerate(iterator, start=1):
        block = process_block(block)    # process your block data

        with open(f'{index}.txt', 'w') as f_out:
            f_out.write(block)

5voto

TonyCoolZhu Punkte 71

Ich denke, wir können das so schreiben:

def read_file(path, block_size=1024): 
    with open(path, 'rb') as f: 
        while True: 
            piece = f.read(block_size) 
            if piece: 
                yield piece 
            else: 
                return

for piece in read_file(path):
    process_piece(piece)

2voto

sinzi Punkte 141

Ich darf aufgrund meines schlechten Rufs keine Kommentare abgeben, aber SilentGhosts Lösung sollte mit file.readlines([sizehint]) viel einfacher sein

python datei methoden

edit: SilentGhost hat recht, aber das sollte besser sein als:

s = "" 
for i in xrange(100): 
   s += file.next()

1voto

SilentGhost Punkte 285785

Ich befinde mich in einer ähnlichen Situation. Es ist nicht klar, ob Sie die Chunk-Größe in Bytes kennen. Ich kenne sie normalerweise nicht, aber die Anzahl der erforderlichen Datensätze (Zeilen) ist bekannt:

def get_line():
     with open('4gb_file') as file:
         for i in file:
             yield i

lines_required = 100
gen = get_line()
chunk = [i for i, j in zip(gen, range(lines_required))]

Update : Danke nosklo. Das ist, was ich meinte. Es funktioniert fast, außer dass es eine Zeile "zwischen" Chunks verliert.

chunk = [next(gen) for i in range(lines_required)]

Erfüllt den Zweck, ohne dass Linien verloren gehen, aber es sieht nicht sehr schön aus.

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