stanwin00
Posts: 26
Joined: Tue Aug 06, 2019 9:55 am

python Class and instance attribute

Thu Oct 10, 2019 6:35 am

Hi, i need some help with the following error on my python script. For some reason the error is being thrown for that particular attribute. The error is "class initialiseABC has no instance attribute invalidUser" would appreciate some additional pair of eyes, as far as i know, i've initialized everything. It won't even let me create a new def method to store that attribute. Code is below.

Code: Select all

import Tkinter as tk
import ttk

class initialiseABC:
    
    global dbHost
    global dbName
    global dbUser
    global dbPass
    
    dbHost = 'localhost'
    dbName = 'dbname'
    dbUser = 'dbuser'
    dbPass = 'dbpass'
    
    def __init__(self):
        self.tk = tk.Tk()
        self.frame = tk.Frame(self.tk)
        self.frame.grid()
        self.tk.columnconfigure(0, weight=1)
        
        self.tk.attributes('-zoomed', True)
        self.tk.attributes('-fullscreen', True)
        self.state = True
        self.tk.bind("<F11>", self.toggle_fullscreen)
        self.tk.bind("<Escape>", self.end_fullscreen)
        self.tk.config(cursor="mouse", bg="white")
        
        self.show_idle()
        
        t = Thread(target=self.rfid_listen)
        t.daemon = True
        t.start()
        
    def show_idle(self):
        self.image = tk.PhotoImage(file="pic.gif")
        self.photoLabel = tk.Label(self.tk, image=self.image, borderwidth=0, highlightthickness=0)
        self.photoLabel.grid(row=10, columnspan=3)
        self.welcomeLabel = tk.Label(self.tk, text="Welcome to ABC Workplaces.\nPlease select an option below or tap your RFID card")
        self.welcomeLabel.config(font='size, 20', justify='center', anchor='center', bg="white")
        self.welcomeLabel.grid(sticky=tk.W+tk.E, pady=5)
         
    def forgetWelcomeMessage(self):
        self.photoLabel.grid_forget()
        self.welcomeLabel.grid_forget()
        self.QRBtn.grid_forget()
        self.SMSBtn.grid_forget()

    def returnToIdle(self):
        self.validUser.grid_forget()
        GPIO.output(12, GPIO.LOW)
        self.show_idle()        

       
    def rfid_listen(self):

        try:
        # Welcome message
            print("Welcome to the MFRC522 data read example")
            print("Press Ctrl-C to stop.")

            while True:
                rfid_presented = ""
                dbConnection = MySQLdb.connect(host=dbHost, user=dbUser, passwd=dbPass, db=dbName)
                cur = dbConnection.cursor(MySQLdb.cursors.DictCursor)
                # Get the UID of the card
                id = reader.read_id()
                print(id)
                cur.execute("SELECT * FROM access_list WHERE rfid_code = '%s'" % (id))
                if cur.rowcount != 1:
                    print ("Access Denied")
                    self.forgetWelcomeMessage()
                    self.invalidUser = tk.Label(self.tk, text="You are not authorized to enter the premise.\nPlease contact the administrator")
                    self.invalidUser.config(font='size, 20', justify='center', anchor='center', bg="white")
                    self.invalidUser.grid(row=4, columnspan=3, sticky=tk.W+tk.E)
                    time.sleep(3)
                    self.returnToIdle()
                # Log access attempt
                    cur.execute("INSERT INTO access_log SET rfid_presented = '%s', rfid_presented_datetime = NOW(), rfid_granted = 0" % (id))
                    dbConnection.commit()

                    time.sleep(3)
                else:
                    user_info = cur.fetchone()
                    self.forgetWelcomeMessage()
                    self.validUser = tk.Label(self.tk, text="Welcome %s \nto ABC Workplaces!" % (user_info['name']), font='size, 40', justify='center', anchor='center')
                    self.validUser.config(font='size, 20', justify='center', anchor='center', bg="white")
                    self.validUser.grid(columnspan=3, sticky=tk.W + tk.E, pady=200)
                    GPIO.output(12,GPIO.HIGH)
                    # Log access attempt
                    cur.execute("INSERT INTO access_log SET rfid_presented = '%s', rfid_presented_datetime = NOW(), rfid_granted = 1" % (id))
                    dbConnection.commit()
                    accessLogId = cur.lastrowid
                    time.sleep(5)
                    self.returnToIdle()
                    rfid_presented = ""
                    dbConnection.close()

        finally:
            GPIO.cleanup()
            
 if __name__ == '__main__':
    w = initialiseABC()
    w.tk.mainloop()
    
Error pops up when i try to add "self.invalidUser.grid_forget()" into the method returnToIdle(self). Not sure what is happening here though any help would be appreciated.

User avatar
joan
Posts: 14473
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: python Class and instance attribute

Thu Oct 10, 2019 8:20 am

The script you posted does not show that error.

Code: Select all

python rpi-q1007.py
Traceback (most recent call last):
  File "rpi-q1007.py", line 103, in <module>
    w = initialiseABC()
  File "rpi-q1007.py", line 25, in __init__
    self.tk.bind("<F11>", self.toggle_fullscreen)
AttributeError: initialiseABC instance has no attribute 'toggle_fullscreen'

scotty101
Posts: 3750
Joined: Fri Jun 08, 2012 6:03 pm

Re: python Class and instance attribute

Thu Oct 10, 2019 8:26 am

1. You seem to be using Python 2 (given by the upper case Tkinter), use Python3.
2. It is not a good idea to run a method of a class as a separate thread. If you want to have a separate thread, keep it as a separate function but when you create the thread, pass it a reference to the instance of your class.
3. Mixing GUI and database code (business logic) is messy. Keep your queries to the database as something you do inside separate functions or even a class which can store all the variable related to the db password/username/cursor etc.
4. In your init method create the invalid_user attribute like so

Code: Select all

self.invalid_user = None
then you should be able to refer to it. Likely problem is that you are trying to access it before it exists.
Electronic and Computer Engineer
Pi Interests: Home Automation, IOT, Python and Tkinter

stanwin00
Posts: 26
Joined: Tue Aug 06, 2019 9:55 am

Re: python Class and instance attribute

Thu Oct 10, 2019 8:47 am

thanks @scotty101 I have yet to refactor the database bit. And yes you are right, i needed to call my instance first. Thanks all for the suggestions, I found the fix.

Return to “Python”