file.read()-Größe automatisch einsetzen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
DMD-OL
User
Beiträge: 315
Registriert: Samstag 26. Dezember 2015, 16:21

hey ho,
wie bekomm ich die größe einer datei, die ich dann in file.read() verwenden kann?
ich verwende eine Beispieldatei in der nur "Hallo, na wie gehts?" steht.
Damit funktioniert alles:

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf-8 -*-

import time
import numpy as np
import csv
import os

desktopFile = os.path.expanduser("~\Desktop")
path_grund = desktopFile+'\Handy-Datenbank'
path_folder = path_grund+'\\Beispiel.001'

filesize = os.stat(path_folder).st_size
print filesize

f = open(path_folder, 'rb')
def count(f):
    while 1:
        block = f.read(filesize)
        if not block:
             break
        yield block.split(";")

linecount = count(f)
print next(linecount)
Zum weiteren Testen größerer Dateien benutze ich eine DATANORM.001-Datei (schon ziemlich groß :))
Damit funktioniert es nicht :(
ich bekomme ein Exception:

Code: Alles auswählen

Message	File Name	Line	Position	
Traceback				
    <module>	C:\Users\DMD-OL\Desktop\Handy-Datenbank\Einlesen.py	25		
    count	C:\Users\DMD-OL\Desktop\Handy-Datenbank\Einlesen.py	19		
exceptions.MemoryError				
Als Größe der DATANORM.001 wird 325315663 (bytes?) angegeben.
Was ist da falsch?
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

der Code ist... komisch. Was ist das Ziel der Aktion?

Gruß, noisefloor
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@DMD-OL: was für ein System hast Du, wo ein paar hundert Megabytes schon Probleme machen?

Dein Programm ist schon viel zu kompliziert. Pfade setzt man mit `os.path.join` zusammen. `filesize` kommt auf magische Weise in die Funktion `count`. `count` ist ein komischer Name, für das was die Funktion macht. `read` ohne Parameter liest schon die gesamte Datei, da braucht man also nicht erst umständlich die Größe ermitteln. Wenn man die ganze Datei liest, dann wird die while-Schleife exakt ein mal durchlaufen. Man sollte nicht Funktionsdefinitionen mit ausführbarem Code mischen. Dateien immer mit dem with-Statement öffnen.

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf-8 -*-
import os

def count(f):
    block = f.read()
    return block.split(";")

database_filename = os.path.expanduser("~/Desktop/Handy-Datenbank/Beispiel.001")
with open(database_filename, 'rb') as f:
    linecount = count(f)
    print linecount
Wenn die Daten nicht mehr in den Speicher passen, dann mußt Du wirklich blockweise lesen. Da ist dann die Gesamtgröße auch egal, denn Du rufst `read` mit einer sinnvollen Blockgröße auf.
DMD-OL
User
Beiträge: 315
Registriert: Samstag 26. Dezember 2015, 16:21

ich hab eine riesige DATANORM.001-Datei.
und ich versuche die einfach in eine datenbank zu schreiben bzw. nur erst einmal zu printen.
daher lese ich die datei ein und versuche durch den yield-befehl alles auszulesen, ohne extra in den speicher, ohne memory(?), zu schreiben.
wie kann man eine text-datei den blockweise lesen? da brauch man doch sowas wie:
block = f.read(anfang,ende)
oder noch besser
block = f.readline(anfang,ende) --> so was wär richtig geil :)
lg
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Du musst das Ende der Datei für häppchenweises Lesen nicht kennen. Das Dateiobjekt hat einen Zeiger, der sich die aktuelle Position merkt. Bei read(n) rutscht er um n Stellen in Richtung Dateiende. Wenn er ganz am Ende steht, dann gibt read(n) eine leere Zeichenkette zurück. Folglich kann man sowas machen:

Code: Alles auswählen

def read_chunks(f, size):
    while True:
        chunk = f.read(size)
        if not chunk:
            return
        yield chunk

# oder alternativ:
def read_chunks(f, size):
    return iter(lambda: f.read(size), '')
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
daher lese ich die datei ein und versuche durch den yield-befehl alles auszulesen, ohne extra in den speicher, ohne memory(?), zu schreiben.
Mit `read` liest du aber in den Speicher. Und ich weiß ja nicht, welche Vorstellung du davon hast, was `yield` macht - aber es macht definitiv nicht das, was du dir denkst / erhoffst. In deinem Code macht es jedenfalls keinen Sinn.

Und du bist auf die Frage von Sirius3 nicht eingegangen: deine Datei ist ca. 325 MB groß - das ist nicht viel und erst recht nicht "riesig". Es ist doch seit mehreren Jahren Standard, dass Rechner mit 4 GB RAM haben. Oder machst du das am Raspi 1 oder Zero? Den wird es in der Tat eng...

Gruß, noisefloor
Antworten