2

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

Liana
  • 314
  • 5
  • 15
  • As a programmer you should try very, *very*, **very** hard not to use globals. – quamrana Nov 05 '20 at 18:11
  • @quamrana What are the other methods than using `global` here? Maybe passing as parameters? – Delrius Euphoria Nov 05 '20 at 18:18
  • @quamrana yes use of global variable should not be used –  Nov 05 '20 at 18:19
  • Also as a tip, your `result_label` is `None`, meaning it cannot be edited elsewhere. – Delrius Euphoria Nov 05 '20 at 18:23
  • Just found that alternatively you can do as Rice said in the answer, and make your buttons command into `sub_btn=tk.Button(...,command = lambda:submit(numcheck,charcheck))`. This way you can get rid of `global` and resetting of values – Delrius Euphoria Nov 05 '20 at 18:26
  • Does this answer your question? [Local variable referenced before assignment error python](https://stackoverflow.com/questions/32727258/local-variable-referenced-before-assignment-error-python) –  Nov 06 '20 at 10:03

5 Answers5

3

You should move charcheck and numcheck into your function:

def submit():
    charcheck = 0
    numcheck = 0
quamrana
  • 37,849
  • 12
  • 53
  • 71
  • Ah, yes! It works now, thank you :)) I'll accept your answer in a few minutes – Liana Nov 05 '20 at 18:18
  • @Liana But keep in mind, that when ever the function is run, the value of `charcheck` and `numcheck` will be reset to 0, keep that in mind, might be helpful elsewhere – Delrius Euphoria Nov 05 '20 at 18:21
1

Use the global call to access the global variables

def submit(): 
    global numcheck, charcheck
    ......
Mike67
  • 11,175
  • 2
  • 7
  • 15
1

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

quamrana
  • 37,849
  • 12
  • 53
  • 71
1

You can also do this:

def submit(numbcheck,charcheck)



sub_btn=tk.Button(...,command = lambda:submit(numcheck,charcheck))
  • Would be better if you could also change this to show how the button should accept the function, as there are arguments parameters defined here. – Delrius Euphoria Nov 05 '20 at 18:29
  • 1
    @cool cloud ok but you have already told how to do that in the comment anyways i will edit it and put it. –  Nov 06 '20 at 05:00
0

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.