Struggling with Class variable and Instances between my modules

Here are the relevant code sections:

main.py

from utilities import LoggerSettings
class MainApp:
    def __init__(self):

   def get_settings(self):
        self.settings = LoggerSettings.retrieve_settings(self.site_name.value)

        if self.settings[0]["File Exists"]:
            load_settings = PopupHandler.popup_create(
                {
                    "Type": "yesno",
                    "Title": "Load Settings",
                    "Message": "Settings file found. Load settings?",
                }
            )
            if load_settings:
                self.open_window(DataDisplayPage, "Logging")
        else:
            PopupHandler.popup_create(
                {
                    "Type": "info",
                    "Title": "Config",
                    "Message": "No settings file found. Please configure settings.",
                }
            )

utilities.py

class LoggerSettings:
    site_name = ""
    settings_directory = "/home/ect-one-user/Desktop/One_Water_Pulse_Logger/config/"
    settings_filename = "_logger_config.json"
    settings_json = {}

    def retrieve_settings(site_name):
        LoggerSettings.site_name = site_name
        json_file = LoggerSettings.settings_directory + site_name + LoggerSettings.settings_filename

        if exists(json_file):
            with open(json_file, 'r') as json_data:
                LoggerSettings.settings_json = json_data.read()

            json_data.close()

            return {"File Exists" : True}, LoggerSettings.settings_json

        else:
            return {"File Exists" : False}, LoggerSettings.settings_json

pulse_logger.py

from utilities import LoggerSettings

class DataLogger:

    settings = LoggerSettings.settings_json

    def save_logging():
        dl = DataLogger
        if dl.settings["Data Output"]["Location"] == "local":
            data_save = dl.write_log_to_db
        else:
            data_save = dl.write_log_to_file

Maverick494/One_Water_Pulse_Logger (github.com) Here is the whole code base; I just git committed so it should be up to date since I am working in main.

Here is the error:

Exception in thread Thread-3:
Traceback (most recent call last):
  File "/usr/lib/python3.9/threading.py", line 954, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.9/threading.py", line 892, in run
    self._target(*self._args, **self._kwargs)
  File "/home/ect-one-user/Desktop/One_Water_Pulse_Logger/gui_app/logging_data_display.py", line 180, in save_logging
    DataLogger.save_logging()  # Call the save_logging method in DataLogger
  File "/home/ect-one-user/Desktop/One_Water_Pulse_Logger/gui_app/pulse_logger.py", line 61, in save_logging
    if dl.settings["Data Output"]["Location"] == "local":
KeyError: 'Data Output'

I had printed LoggerSettings.settings_json in pulse_logger just before this attempts to run and it only shows {'Site Name': 'Test_Site'}

If I print it in utilities.py I get the expected JSON which contains the key.

I am open to suggestions at this point for how to fix this. I am also open to any other suggestions around the code if anyone has any.

I may have time to look at this in more detail later, but a few quick thoughts:

Depending on where else these classes are used, you may not need classes here at all. As they are now, LoggerSettings.retrieve_settings and DataLogger.save_logging should be marked with @classmethod so they are set up correctly. But neither look like they actually need much persistent state, so you may be able to make them functions in their modules and avoid classes entirely. If they need a little bit of global state a module level variable can work for that too. I mention this because it could potentially remove a layer of complexity from the problem you’re having.

I do see in your stack trace that the exception is off the main thread, and from context you’re probably using some UI library. If parts of the code you posted are executing on different threads then you can see strange out of order behavior. When using threads it is helpful to be very specific about what threads own what data and when data is moved between them, because a lot of multithreaded bugs have to do with sharing data such that two threads try to modify it at the same time (“data races”).

As posted there are some syntactic oddities, but I’m assuming the code blocks are extracts from your full project so I won’t comment on that without looking at the whole project.

Yes, this is very cut down code. I was trying to just give the “problem” spots.

This is supposed to be a UI that can display the output of a pulse sensor. In this case a flow meter. I have an UI where you can build settings for a site and save them to a JSON file. If you enter a site name that already has a setting file you can opt to load the previous settings. These settings are then used in several places; maybe I am over complicating it though.

Do you understand how this relates to the error that you are seeing?

What do you think the value should be instead? Step by step, what is your reasoning for expecting that?

Have you read How to Debug Small Programs?

Just to make sure you understand: git commit does not update anything anywhere except your own working directory and corresponding local repository. You need git push to upload to GitHub (and you must have configured the remote for it already). When I check your repository link, it tells me that the last commit was 2 weeks ago.

Yes, I do understand how it relates to the error I am seeing. When the MainApp class takes Test_Site in on the input page and calls LoggerSettings.retrieve_settings(self.site_name.value) it SHOULD be, during that function run, retrieving the existing JSON file (yes it exists).

That retrieval SHOULD (and seems to) be assigned to the class, LoggerSettings, variable settings_json to the dictionary translated from the saved json. Which, when printed in the if exists from retrieve settings AND printing self.settings[1] in MainApp after running that function, shows the following

{"Site Name": "Test_Site", "Data Output": {"Location": "local", "Email Address": ""}, "Sensor": {"Name": "Test_Sensor", "K Factor": "7.5", "Standard Unit": "lpm", "Desired Unit": "gpm"}}

However, when LoggerSettings.settings_json is assigned in DataLogger to settings, it is showing {"Site Name": "Test_Site"}. Now, this is where my very little usage of classes is impacting my ability to understand the issue. It seems as though one of two things is happening - 1. The DataLogger class is getting the settings_json BEFORE the MainApp is retrieving the settings file and never getting an updated settings OR 2. The DataLogger is for some reason not using the same instance of the LoggerSettings class. However, there could be other reasons I am not aware of.

Now, there is also the process where in I create a new site and setup the dictionary to create the json file. When I do that I get the following json when I print the settings in DataLogger

{'Site Name': 'Test_Site_1', 'Data Output': {'Location': 'local', 'Email Address': 'test_email_1@email.com'}, 'Sensor': {'Name': 'test_fm_1', 'K Factor': '7.5', 'Standard Unit': 'lpm', 'Desired Unit': 'gpm'}}

There is a whole other issue to deal with later after clicking start logging, but at least when I create a new site it sees the config dictionary. The only issue seems to occur when an existing site is pulled in MainApp.

As for the Git Commit, yes I should’ve said push and I thought I had clicked the sync button on VSCode but I guess I didn’t. So I pushed this morning.

Edit: Yes, I stepped into the deep end with this project being rusty in coding at all and not even having written test cases in the past because my simple scripts never needed it. So, yes I am going to have to learn a lot more; however, in this case I have been trying for weeks to figure this out on my own and I asked here for a very small piece of the multiple problems help. If I had time to read an article that really is just patronizing and elitist for basically the first half of it I would’ve. I intentionally avoided asking this question on SO because of that attitude and I see I cannot get away from it.