Python buffern bei Datei lesen

Gast #6688571
Lesenswert?
• ▲
▼
Hi,

ich versuche die Frage gank knapp zu stellen:

Wenn ich in Python ein (text)file öffne, kann ich da Zeilenweise drüber 
iterieren. Also per
1
for line in file:
2
    print(line)

ich kann auch einen größeren Block lesen:
1
buffer = file.read(512)
2
for foo in buffer:
3
    print(foo)
Wenn ich jetzt aber in dem Buffer iteriere ist das Zeichenweise.

Wie kann ich größere Sektoren per file.read() holen und da dann auch 
Zeilenweise iterieren? (Oder passiert das ggf. sogar 'unter der Haube')?


danke euch!
#6711436
Lesenswert?
• ▲
▼
Thomas Barends schrieb:
> Ist das hier was?
>
> myfile=open('myfilename.txt','r')
> mylines=myfile.readlines()
> myfile.close()
>
> for line in mylines:
>     # DO THING WITH LINE

Das ist zwar richtig, aber je nach Anwendungsfall leider nur so... 
"halbschön", da die Datei auf diese Weise komplett in den Speicher 
geladen wird, was bei sehr großen Dateien etwas... problematisch werden 
kann. Zudem entfernt die Methode "readlines()" leider nicht den 
Zeilenumbruch am Ende der Zeilen.

Allerdings kann unser TO auf seinen Puffer die Methode "splitlines()" 
anwenden, die die Zeilenumbrüche entfernt, sich aber nicht an 
Zeilenumbrüchen orientiert. Ein "read(512).splitlines()" enthält im 
letzten Feld also mit einer sehr hohen Wahrscheinlichkeit eine 
unvollständige Zeile. Deswegen wäre so etwas wie
1
with open(filename, 'r') as ifh:
2
    bufferlist = ifh.read(BUFSIZE).splitlines()
3
    bufferlist[-1] += ifh.readline().strip()

vielleicht ein hübscherer Weg, die letzte Zeile vollständig zu lesen 
(readline()) und auch dort den Zeilenumbruch zu entfernen (strip()).
Gast #6711629
Lesenswert?
• ▲
▼
Sheeva P. schrieb:
> vielleicht ein hübscherer Weg, die letzte Zeile vollständig zu lesen
> (readline()) und auch dort den Zeilenumbruch zu entfernen (strip()).

Vielleicht kann man das so umsetzen, das Ganze ist ein Generator, 
welcher die Datei Sektoren weise einließt und zeilenweise ausgibt.
1
from typing import Iterator
2

3
def lineread(fname: str) -> Iterator[bytes]:
4
    carry = bytes()
5
    with open(fname, 'rb') as fin:
6
         for chunk in iter(fin.read, b''):
7
             carry += chunk
8
             arr = carry.splitlines()
9
             yield from arr[:-1]
10
             carry = arr[-1]
11
         yield carry
Gast #6711739
Lesenswert?
• ▲
▼
Nun auch in Funktioniernd, wenn das universal newline sich auf zwei 
Chunks verteilt.
1
def lineread(fname: str) -> Iterator[bytes]:
2
    carry = bytes()
3
    def rm_univeral_newline(x: bytes) -> bytes: return x.splitlines()[0]
4
    with open(fname, 'rb') as fin:
5
         for chk in iter(fin.read, b''):
6
               carry += chk
7
               arr = carry.splitlines(keepends=True)
8
               for x in arr[:-1]:
9
                   yield rm_univeral_newline(x)
10
               carry = arr[-1]
11
         yield rm_univeral_newline(carry)

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.