Seite 1 von 1

Eingelesene Dateien aus Json geht verloren

Verfasst: Donnerstag 30. Juli 2020, 06:24
von Hartmannsgruber
Servus Forum,

ich habe einen für mich unerklärlichen Fehler gefunden.

Code: Alles auswählen

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

import csv
import json
import logging
import os
import platform
import sys
from pathlib import Path
from PyQt5 import uic
from PyQt5.QtCore import QCoreApplication
from PyQt5.QtWidgets import (QAbstractItemView, QApplication, QComboBox,
                             QCompleter, QFormLayout, QHBoxLayout,
                             QInputDialog, QLabel, QLineEdit, QMainWindow,
                             QMessageBox, QPushButton, QTableWidget,
                             QTableWidgetItem, QTextEdit, QTreeView,
                             QVBoxLayout, QWidget)

log_format = "%(levelname)s : %(asctime)s : Zeile: %(lineno)s : %(message)s"
logging.basicConfig(filename="infolog.log", level=logging.INFO,
                    format=log_format)

if platform.system() == "Linux":
    listenpfad = str(Path().absolute()) + "/Listen/"
    grafikpfad = str(Path().absolute()) + "/Grafiken/"
    uipfad = str(Path().absolute()) + "/Ui/"
elif platform.system() == "Windows":
    listenpfad = str(Path().absolute()) + "\\Listen\\"
    grafikpfad = str(Path().absolute()) + "\\Grafiken\\"
    uipfad = str(Path().absolute()) + "\\Ui\\"

zutatendatei = listenpfad + "Zutaten.json"
mengeneinheitendatei = listenpfad + "Mengeneinheiten.csv"

mainwindow_ui = uipfad + "mainwindow.ui"

mengeneinheiten = []
zutaten = {}

class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)        
        uic.loadUi(mainwindow_ui, self)
        print(mengeneinheiten)
        print(zutaten)
        
        self.show()


def lade_aus_json(dateiname, zieldatei, loggingbezeichnung):
    with open(dateiname, "r", encoding="utf-8") as jsonfile:
        zieldatei = json.load(jsonfile)
    logging.info("Die " + loggingbezeichnung + " wurde aus der Jsondatei " + \
                    " eingelesen.")

def lade_aus_csv(dateiname, zielliste, loggingbezeichnung):
    with open(dateiname, "r", encoding="utf-8", newline="") as csvfile:
        reader = csv.reader(csvfile, delimiter=";")
        
        [zielliste.append(element[0]) for element in reader]
    logging.info("Die " + loggingbezeichnung + " wurde aus der CSV Datei " + \
                    " eingelesen.")


def main(): 
    lade_aus_json(zutatendatei, zutaten, "Zutaten")
    lade_aus_csv(mengeneinheitendatei, mengeneinheiten, "Mengeneinheiten")
    
    app = QApplication(sys.argv)
    mainwindow = MainWindow()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()
Es wird je eine CSV und eine JSON Datei eingelesen.
Die csv Datei erhält die Werte durch die Funktion "lade_aus_csv".
Rufe ich nun Variable in der Instanz der Klasse MainWindow auf, so enthält sie Daten.
Die json Datei erhält die Werte durch die Funktion "lade_aus_json".
Rufe ich aber diese Variable in der Instanz der Klasse MainWindow auf, so ist die Variable ohne Leer.

Warum greift nun genau die Instanz auf die Variable mit den leeren Werten zu und auch nur bei der json Datei?
Bitte um Erklärung.

Liegt in diesen Fall eine harte Kodierung vor, bzw. sind die Pfade richtig als Absolute Pfade gesetzt?

Vielen Dank!

Re: Eingelesene Dateien aus Json geht verloren

Verfasst: Donnerstag 30. Juli 2020, 07:39
von Sirius3
Du benutzt pathlib.Path stückelst dann aber je nach Betriebssystem Pfade per String+ zusammen. WARUM?
Benutze keine globalen Variablen. Alles was eine Funktion braucht, bekommt sie über ihre Argumente, hier aber: die Ergebnisse liefert sie per `return` zurück.
Listcomprehensions sind KEIN Ersatz für for-Schleifen, wenn mit dem Ergebnis der Liste gar nichts gemacht wird, oder das, was innerhalb passiert Nebeneffekte hat.
Strings setzt man nicht per + zusammen, sondern benutzt format-Strings.
KONSTANTEN schreibt man komplett GROSS.
`zieldatei` wird in `lade_aus_json` als Argument benutzt und nicht verwendet und als Lokale Variable definiert und nicht benutzt. Der Name zieldatei ist auch falsch, da es sich gar nicht um eine Datei handelt.
Fenster sollte sich nicht selbst darstellen, das show gehört aus __init__ raus.

Code: Alles auswählen

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import csv
import json
import logging
import sys
from pathlib import Path
from PyQt5 import uic
from PyQt5.QtCore import QCoreApplication
from PyQt5.QtWidgets import (QAbstractItemView, QApplication, QComboBox,
                             QCompleter, QFormLayout, QHBoxLayout,
                             QInputDialog, QLabel, QLineEdit, QMainWindow,
                             QMessageBox, QPushButton, QTableWidget,
                             QTableWidgetItem, QTextEdit, QTreeView,
                             QVBoxLayout, QWidget)

LOG_FORMAT = "%(levelname)s : %(asctime)s : Zeile: %(lineno)s : %(message)s"
LOG_FILENAME = "infolog.log"

BASE_PATH = Path().absolute()
LIST_PATH = BASE_PATH / "Listen"
GRAPHICS_PATH = BASE_PATH / "Grafiken"
UI_PATH = BASE_PATH / "Ui"
ZUTATEN_PATH = LIST_PATH / "Zutaten.json"
MENGENEINHEITEN_PATH = LIST_PATH / "Mengeneinheiten.csv"
MAINWINDOW_UI = UI_PATH / "mainwindow.ui"

class MainWindow(QMainWindow):
    def __init__(self, mengeneinheiten, zutaten):
        QMainWindow.__init__(self)        
        uic.loadUi(MAINWINDOW_UI, self)
        print(mengeneinheiten)
        print(zutaten)

def lade_aus_json(dateiname, loggingbezeichnung):
    with open(dateiname, encoding="utf-8") as jsonfile:
        result = json.load(jsonfile)
    logging.info(f"Die {loggingbezeichnung} wurde aus der Jsondatei eingelesen.")
    return result

def lade_aus_csv(dateiname, loggingbezeichnung):
    with open(dateiname, encoding="utf-8", newline="") as csvfile:
        reader = csv.reader(csvfile, delimiter=";")
        result = [element[0] for element in reader]
    logging.info(f"Die {loggingbezeichnung} wurde aus der CSV Datei eingelesen.")
    return result

def main(): 
    logging.basicConfig(filename=LOG_FILENAME, level=logging.INFO, format=LOG_FORMAT)
    zutaten = lade_aus_json(ZUTATEN_PATH, "Zutaten")
    mengeneinheiten = lade_aus_csv(MENGENEINHEITEN_PATH, "Mengeneinheiten")
    app = QApplication(sys.argv)
    mainwindow = MainWindow(mengeneinheiten, zutaten)
    mainwindow.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()
Normalerweise möchte man Dateien nicht relativ zum aktuellen Arbeitsverzeichnis ablegen, sondern relativ zur Pythondatei:

Code: Alles auswählen

BASE_PATH = Path(__file__).absolute().parent

Re: Eingelesene Dateien aus Json geht verloren

Verfasst: Donnerstag 30. Juli 2020, 17:40
von Hartmannsgruber
Wann werden dann globale Variablen verwendet?
Wie soll z.B. gehandhabt werden, wenn zwei verschiedene Klassen auf ein und die selbe Variable zugreifen?

Ich habe nach Betriebssystem unterschieden, da ja Linux und Windows einen unterschied mit den Strichen in
Pfadangaben machen ( "/", "\"). War mein Gedankengang hier zu kompliziert, oder habe ich dies falsch verstanden?
ich wollte einen absoluten Pfad zur Datei angeben.

Das mit den aufruf von .show() habe ich aus dem Buch von Herrn Weigend. Dieser ruft die Funktion in der __init__
Anweisung auf. Werde es aber umgehend umstellen.

Re: Eingelesene Dateien aus Json geht verloren

Verfasst: Donnerstag 30. Juli 2020, 18:25
von Sirius3
Man verwendet nie globale Variablen. Wenn verschiedene Klassen oder Funktionen oder was auch immer Zugriff brauchen, werden die Variablen als Argumente übergeben.
Und für Pfade gibt es ja Path-Objekte, was Du ja auch benutzt hast, nur eben falsch.

Re: Eingelesene Dateien aus Json geht verloren

Verfasst: Freitag 31. Juli 2020, 10:12
von peterpy
Hallo Hartmannsgruber ,
Wie soll z.B. gehandhabt werden, wenn zwei verschiedene Klassen auf ein und die selbe Variable zugreifen?
zum Beispiel so:

Code: Alles auswählen

class A(object):
    def __init__(self, variable):
        self.variable = variable        
        print("Klasse A, Methode init:", self.variable)
        self.start_klasse_b()            

    def start_klasse_b(self):
        b = B(self.variable)
        variable_aendern = b.variable_aendern()
        self.variable = b.variable_ausgebe()
        print("Klasse A, Methode start_klasse_b:", self.variable)

class B(object):
    def __init__(self, variable):
        self.variable = variable        
        self.variable_ausgebe()

    def variable_aendern(self):
        self.variable = "Veränderte Variable aus Klasse B"

    def variable_ausgebe(self):
        print("Klasse B, Methode variable_ausgebe:", self.variable)
        return self.variable

if __name__ == "__main__":
    start = A(variable = "Ursprüngliche Variable aus Klasse A")
Gruss
Peter

Re: Eingelesene Dateien aus Json geht verloren

Verfasst: Freitag 31. Juli 2020, 10:50
von Sirius3
@Peter: dass eine Methode die variable_ausgebe heißt, eine Variable zurückgibt ist sehr seltsam. Man würde auch direkt auf b.variable zugreifen.
`variable_aendern` liefert richtigerweise nichts zurück. Das Nichts an eine lokale Variable variable_aendern zu binden, macht keinen Sinn.