Python local variable 'charcheck' referenced before assignment, why?

Viewed 774

I'm trying to write a password validator application using python tkinter. If the inserted password contains at least 2 numbers, at least 2 special characters and a length of at least 7, the password is considered Strong, else Weak.

If I enter a weak password the program will work, but if I enter a strong password I face this error:

Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python3.8/tkinter/__init__.py", line 1883, in __call__
    return self.func(*args)
  File "/home/liana/projects/python/modification/modify.py", line 15, in submit
    charcheck += 1
UnboundLocalError: local variable 'charcheck' referenced before assignment

I don't know why.

Here's my code:

import tkinter as tk 

numcheck = 0
charcheck = 0

root=tk.Tk()  
root.geometry("600x400")  
passw_var=tk.StringVar() 

def submit(): 
    password=passw_var.get()    
    passw_var.set("")
    for i in range(len(password)):
        if(password[i]=='!' or password[i]=='@' or password[i]=='#' or password[i]=='$' or password[i]=='&' or password[i]=='%' or password[i]=='*'):
            charcheck += 1

        elif (ord(password[i])>=48 and ord(password[i])<=57):
            numcheck += 1 

    if (len(password)>=7 and charcheck>=2 and numcheck>=2):
        result_label = tk.Label(root, text='STRONG', font=('calibre',10, 'bold')).grid(row=3, column=2)

    else:
        result_label = tk.Label(root, text='WEAK', font=('calibre',10, 'bold')).grid(row=3, column=2)
       
passw_label = tk.Label(root, text = 'Enter Your password: ', font = ('calibre',10,'bold')) 
   
passw_entry=tk.Entry(root, textvariable = passw_var, font = ('calibre',10,'normal'), show = '*') 
   
sub_btn=tk.Button(root,text = 'Submit', 
                  command = submit) 
   
passw_label.grid(row=1,column=0) 
passw_entry.grid(row=1,column=1) 
sub_btn.grid(row=2,column=1) 
   
root.mainloop() 

I'd like to know where I'm making a mistake. Thank you

5 Answers

You should move charcheck and numcheck into your function:

def submit():
    charcheck = 0
    numcheck = 0

Use the global call to access the global variables

def submit(): 
    global numcheck, charcheck
    ......

Your function def submit doesn't know about the charcheck variable. You have to say to your function that it's global:

def submit():
    global charcheck
    password=passw_var.get()    
    passw_var.set("")
    for i in range(len(password)):

So it works, adding global charcheck

You can also do this:

def submit(numbcheck,charcheck)



sub_btn=tk.Button(...,command = lambda:submit(numcheck,charcheck))

Your function is looking for the variable name in it's local scope (within it's indentation). If you don't understand, look up Python Variable scope tutorials. You can resolve the problem in two ways; pass the variables as arguments or use the global keyword, such as in the code bellow:

def submit(): 
    global charcheck, numcheck, passw_var

    special_chars = "!@#$%^&*()_+[]\;',./{}|:\"<>?`~"
    password=passw_var.get()    
    passw_var.set("")
    for i in range(len(password)):
        if(password[i]) in special_chars:
            charcheck += 1

        elif (ord(password[i])>=48 and ord(password[i])<=57):
            numcheck += 1 

    if (len(password)>=7 and charcheck>=2 and numcheck>=2):
        result_label = tk.Label(root, text='STRONG', font=('calibre',10, 'bold')).grid(row=3, column=2)

    else:
        result_label = tk.Label(root, text='WEAK', font=('calibre',10, 'bold')).grid(row=3, column=2)

I've also edited the condition to check for special characters, this accounts for all and is more readable.

Related