Home > Software design >  Cannot access variables of an object - 'has no attribute'
Cannot access variables of an object - 'has no attribute'

Time:08-04

Why can I not access any variables that I create in this class? I get Control has no attribute setTemp whenever I try to access it. If I declare it outside __init__ I also get an error. For whatever reason, I can't grasp how to properly declare variables in a Python class, then later use them in methods.

from tkinter import *
from tkinter import ttk
from tkinter import messagebox
from vivTimer import *
import RPi.GPIO as GPO
import threading
import time
import board
import adafruit_dht

dhtDevice = adafruit_dht.DHT22(board.D4, use_pulseio=False)

class Control(object):
    
    setHumid = 95
    timer = 5000
    
    def __init__(self, master):

        setTemp = StringVar()
        setTemp.set('85')

        #set default max temp and humidity

        master.title('Vivarium Control')
        master.resizable(False, False)
        master.configure(background = '#e6e6e6')

        self.style = ttk.Style()
        self.style.configure('TFrame', background = '#e6e6e6')
        self.style.configure('TButton', background = '#e1d8b9')
        self.style.configure('TLabel', background = '#e6e6e6', font = ('Arial', 11))
        self.style.configure('Header.TLabel', font = ('Arial', 18, 'bold'))

        self.frame_header = ttk.Frame(master)
        self.frame_header.pack()

        self.logo = PhotoImage(file = '115500-200.png')
        ttk.Label(self.frame_header, image = self.logo).grid(row = 0, column = 0, rowspan = 2)
        ttk.Label(self.frame_header, text = 'Vivarium Controller', style = 'Header.TLabel').grid(row = 0, column = 1)
        ttk.Label(self.frame_header, wraplength = 300,
                  text = ("Temperature and Humidity control.                "
                          "Enter maximums for both humidity and temperature.")).grid(row = 1, column = 1, padx = 5, sticky = 'nw')

        self.frame_content = ttk.Frame(master)
        self.frame_content.pack()

        ttk.Label(self.frame_content, text = 'Maximum Temp:').grid(row = 0, column = 0, padx = 5, sticky = 'sw')
        ttk.Label(self.frame_content, text = 'Maximum Humidity:').grid(row = 0, column = 1, padx = 5, sticky = 'sw')

        
        self.setTempL = Label(self.frame_content, textvariable = setTemp).grid(row = 0, column = 3, padx = 5, sticky = 'sw')
        ttk.Label(self.frame_content, text = 'Current Humidity:'   str(self.setHumid)).grid(row = 0, column = 4, padx = 5, sticky = 'sw')


        self.entry_temp = ttk.Entry(self.frame_content, textvariable = setTemp, width = 10, font = ('Arial', 10))
        self.entry_humid = ttk.Entry(self.frame_content, width = 10, font = ('Arial', 10))

        self.entry_temp.grid(row = 1, column = 0, padx = 5)
        self.entry_humid.grid(row = 1, column = 1, padx = 5)

        ttk.Button(self.frame_content, text = 'Save',
                   command = self.save).grid(row = 4, column = 0, padx = 5, pady = 5, sticky = 'e')

    def updateLabels(self):
        
        print('blah')
        
    def createTimer(root):
        print('timer 1 sec')
        readTemp = False
        while readTemp == False:
            try:
                # Print the values to the serial port
                temperature_c = dhtDevice.temperature
                temperature_f = temperature_c * (9 / 5)   32
                humidity = dhtDevice.humidity
                
                print(
                    "Temp: {:.1f} F / {:.1f} C    Humidity: {}% ".format(
                        temperature_f, temperature_c, humidity
                    )
                )
                readTemp = True
                if(temperature_f > int(Control.setTemp.get())):
                   print('fan on')

            except RuntimeError as error:
                # Errors happen fairly often, DHT's are hard to read, just keep going
                print(error.args[0])
                time.sleep(2.0)
                continue
            except Exception as error:
                dhtDevice.exit()
                raise error

            time.sleep(2.0)
        
        print(Control.timer)
        root.after(Control.timer, Control.createTimer, root)
        #t2 = threading.Thread(target=VivTimer.startTimer(), args=(10,))
        #t2.start()


    def save(self):

        tempT = self.entry_temp.get()
        self.setTemp = tempT
        print(self.setTemp)
        self.setHumid = self.entry_humid.get()
        Control.updateLabels(self)
        
        print('Temp: {}'.format(self.entry_temp.get()))
        print('Humidity: {}'.format(self.entry_humid.get()))
        self.clear()
        messagebox.showinfo(title = 'Vivarium Control', message = 'Conditions saved!')

    def clear(self):
        self.entry_temp.delete(0, 'end')
        self.entry_humid.delete(0, 'end')



def main():            
    
    root = Tk()
    control = Control(root)
    root.after(1000, Control.createTimer, root)
    root.mainloop()
      
if __name__ == "__main__": main()

CodePudding user response:

I think the following modified version of your code will work much better if you undo all the places I commented out your code (and usually put in a replacement below it). This was necessary to make it possible to run the code at all for testing since I don't have your hardware (or the one image file).

You will need to undo them to try it with your hardware.

The two most significant changes I made were turning setTemp into a class instance attribute and modifying createTimer() to make it a proper class method.

from tkinter import *
from tkinter import ttk
from tkinter import messagebox
#from vivTimer import *
#import RPi.GPIO as GPO
import time
#import board
#import adafruit_dht
#
#dhtDevice = adafruit_dht.DHT22(board.D4, use_pulseio=False)

class Control(object):

    setHumid = 95
    timer = 5000

    def __init__(self, master):
        self.setTemp = StringVar()
        self.setTemp.set('85')

        #set default max temp and humidity

        master.title('Vivarium Control')
        master.resizable(False, False)
        master.configure(background = '#e6e6e6')

        self.style = ttk.Style()
        self.style.configure('TFrame', background = '#e6e6e6')
        self.style.configure('TButton', background = '#e1d8b9')
        self.style.configure('TLabel', background = '#e6e6e6', font = ('Arial', 11))
        self.style.configure('Header.TLabel', font = ('Arial', 18, 'bold'))

        self.frame_header = ttk.Frame(master)
        self.frame_header.pack()

#        self.logo = PhotoImage(file = '115500-200.png')
        self.logo = PhotoImage(file = '8-ball.png')
        ttk.Label(self.frame_header, image = self.logo).grid(row = 0, column = 0, rowspan = 2)
        ttk.Label(self.frame_header, text = 'Vivarium Controller', style = 'Header.TLabel').grid(row = 0, column = 1)
        ttk.Label(self.frame_header, wraplength = 300,
                  text = ("Temperature and Humidity control.                "
                          "Enter maximums for both humidity and temperature.")).grid(row = 1, column = 1, padx = 5, sticky = 'nw')

        self.frame_content = ttk.Frame(master)
        self.frame_content.pack()

        ttk.Label(self.frame_content, text = 'Maximum Temp:').grid(row = 0, column = 0, padx = 5, sticky = 'sw')
        ttk.Label(self.frame_content, text = 'Maximum Humidity:').grid(row = 0, column = 1, padx = 5, sticky = 'sw')


        self.setTempL = Label(self.frame_content, textvariable=self.setTemp).grid(row = 0, column = 3, padx = 5, sticky = 'sw')
        ttk.Label(self.frame_content, text = 'Current Humidity:'   str(self.setHumid)).grid(row = 0, column = 4, padx = 5, sticky = 'sw')


        self.entry_temp = ttk.Entry(self.frame_content, textvariable=self.setTemp, width = 10, font = ('Arial', 10))
        self.entry_humid = ttk.Entry(self.frame_content, width = 10, font = ('Arial', 10))

        self.entry_temp.grid(row = 1, column = 0, padx = 5)
        self.entry_humid.grid(row = 1, column = 1, padx = 5)

        ttk.Button(self.frame_content, text = 'Save',
                   command = self.save).grid(row = 4, column = 0, padx = 5, pady = 5, sticky = 'e')

    def updateLabels(self):

        print('blah')

    def createTimer(self, root):
        print('timer 1 sec')
        readTemp = False
        while readTemp == False:
            try:
                # Print the values to the serial port
#                temperature_c = dhtDevice.temperature
                temperature_c = 30
                temperature_f = temperature_c * (9 / 5)   32
#                humidity = dhtDevice.humidity
                humidity = 20

                print(
                    "Temp: {:.1f} F / {:.1f} C    Humidity: {}% ".format(
                        temperature_f, temperature_c, humidity
                    )
                )
                readTemp = True
                if(temperature_f > int(self.setTemp.get())):
                   print('fan on')

            except RuntimeError as error:
                # Errors happen fairly often, DHT's are hard to read, just keep going
                print(error.args[0])
                time.sleep(2.0)
                continue
            except Exception as error:
#                dhtDevice.exit()
                raise error

            time.sleep(2.0)

        print(Control.timer)
        root.after(Control.timer, self.createTimer, root)

    def save(self):
        tempT = self.entry_temp.get()
        self.setTemp = tempT
        print(self.setTemp)
        self.setHumid = self.entry_humid.get()
        Control.updateLabels(self)

        print('Temp: {}'.format(self.entry_temp.get()))
        print('Humidity: {}'.format(self.entry_humid.get()))
        self.clear()
        messagebox.showinfo(title = 'Vivarium Control', message = 'Conditions saved!')

    def clear(self):
        self.entry_temp.delete(0, 'end')
        self.entry_humid.delete(0, 'end')


def main():
    root = Tk()
    control = Control(root)
    root.after(1000, control.createTimer, root)
    root.mainloop()

if __name__ == "__main__":
    main()

  • Related