Password Generator using Python and Tkinter

Introduction

This is the first blog of the Password Manager using Tkinter series where we are going to create a Password Generator application that will be able to generate strong passwords for us. Since this will be a Graphical User Interface(GUI) application, it doesn't rely on any kind of web connection. This will be a very short blog since the application we are building is quite small. So, let's see what libraries and concepts we are going to use in this application:

So, without further ado, let's get started.

Password Generator Class

Let's start by creating a PasswordGenerator class and define the constructor for it as:

from tkinter import Button, Entry, Frame, Label, LabelFrame, Tk

class PasswordGenerator:

    def __init__ (self):
        self.window = Tk()
        self.window.title("Password Generator")
        self.window.geometry("450x300")

        # Label Frame
        self.label_frame = LabelFrame(
            self.window, text="Enter the number of characters")
        self.label_frame.pack(pady=20)

        # Entry box for number of characters
        self.length_entry_box = Entry(self.label_frame, width=20)
        self.length_entry_box.pack(padx=20, pady=20)

        # Declaring feedback if no length is found
        self.feedback = Label(self.window)

        # Entry box for password
        self.password_entry_box = Entry(
            self.window, text="", width=50)
        self.password_entry_box.pack(pady=20)

        # Frame for buttons
        self.button_frame = Frame(self.window)
        self.button_frame.pack(pady=20)

        # Generate Password Button
        generate_btn = Button(
            self.button_frame, text="Generate Password", command=self.generate_random_password)
        generate_btn.grid(row=0, column=0, padx=10)

        # Copy Password Button
        copy_btn = Button(self.button_frame,
                          text="Copy Password", command=self.copy_password)
        copy_btn.grid(row=0, column=1, padx=10)

In the above script, first of all, we created a window of width 450 and height 300 with the title Password Generator.

Next, if you see in the above output, we have a frame where we have placed an input field so that users can enter the number of characters their password should have. So for that, we have created a LabelFrame called label_frame and packed it with a padding of 20 on the y-axis. Inside the label_frame, we have placed an Entry for password length input called length_entry_box with a width of 20 and padding of 20 on both x-axis and y-axis.

Next, we have an input field where the generated password will appear. For creating the password entry box called password_entry_box, we are again using the Entry class and gave it a width of 50 (since the password can be lengthy too) and a padding of 20 on the y-axis. Above that, we have created a label called feedback using the Label class to show an error message if a user doesn't enter any length and presses Generate Password button.

Below that we'll have a frame called button_frame where our Generate Password and Copy Password buttons will be placed. So to create these buttons, we have used the Button class. The thing to be noticed is we have used two commands - generate_random_password and copy_password for the Generate Password button and Copy Password button respectively. We'll be creating these two methods very soon. We are using grid to place these two buttons in a row.

Generate Password

In the previous section, we saw that we had a generate_random_password method being called when the Generate Password button was clicked. So, let's create that in the PasswordGenerator class itself:

import string
from secrets import choice

UPPERCASE = list(string.ascii_uppercase)
LOWERCASE = list(string.ascii_lowercase)
NUMBER = list(string.digits)
SYMBOLS = ['@', '#', '$', '%', '&', '_']

def generate_random_password(self):
    self.password_entry_box.delete(0, END)
    try:
        password_length = int(self.length_entry_box.get())
        self.feedback.destroy() # Destroy feedback if length is there
        data = UPPERCASE+LOWERCASE+NUMBER + SYMBOLS
        password = ''.join(choice(data) for _ in range(password_length))
        self.password_entry_box.insert(0, password)
    except ValueError:
        self.feedback = Label(self.window, fg="red", text="Please enter number of characters")
        self.feedback.place(x=130, y=100)

First of all, we have imported string and choice(from secrets module). We have then created a few constants such as UPPERCASE , LOWERCASE , NUMBER and SYMBOLS. These constants are Python lists and will be useful when we'll be generating random passwords.

Next, inside the generate_random_password() method, we have first deleted whatever is already present in the password entry box. This is important because we can click on the Generate Password button as many times we want, hence the previous value should be erased before placing the new value. We're then using try-catch block. Inside the try block, we are fetching the value of password length using the get() method provided by the Entry class. We are then converting it into int value. This is where an error can occur when the user doesn't enter any value and clicks on Generate Password button. We are then destroying the feedback message(if any). We are then generating a random password of the desired length using the constants declared above and the choicemethod. Once a new password is generated, it is placed in the password_entry_box.

If the error occurs, we are catching it in the except block and replace the feedback with the error message.

Copy Password

This method will be pretty simple and we'll be using two pre-defined methods given by our Tkinter window.

def copy_password(self):
    self.window.clipboard_clear()
    self.window.clipboard_append(self.password_entry_box.get())

First, we are clearing our clipboard so that if anything is already copied, it is erased. Then we are appending the value which is placed in the password_entry_box.

Run the Mainloop

To run the mainloop, we are using main method as:

if __name__ == ' __main__':
    PasswordGenerator().window.mainloop()

Final Code and Output

Now we are done with our coding part, and you can find the entire code below:

from tkinter import Button, Entry, Frame, Label, LabelFrame, Tk
import string
from secrets import choice
from tkinter.constants import END

UPPERCASE = list(string.ascii_uppercase)
LOWERCASE = list(string.ascii_lowercase)
NUMBER = list(string.digits)
SYMBOLS = ['@', '#', '$', '%', '&', '_']

class PasswordGenerator:

    def __init__ (self):
        self.window = Tk()
        self.window.title("Password Generator")
        self.window.geometry("450x300")

        # Label Frame
        self.label_frame = LabelFrame(
            self.window, text="Enter the number of characters")
        self.label_frame.pack(pady=20)

        # Entry box for number of characters
        self.length_entry_box = Entry(self.label_frame, width=20)
        self.length_entry_box.pack(padx=20, pady=20)

        # Declaring feedback if no length is found
        self.feedback = Label(self.window)

        # Entry box for password
        self.password_entry_box = Entry(
            self.window, text="", width=50)
        self.password_entry_box.pack(pady=20)

        # Frame for buttons
        self.button_frame = Frame(self.window)
        self.button_frame.pack(pady=20)

        # Generate Password Button
        generate_btn = Button(
            self.button_frame, text="Generate Password", command=self.generate_random_password)
        generate_btn.grid(row=0, column=0, padx=10)

        # Copy Password Button
        copy_btn = Button(self.button_frame,
                          text="Copy Password", command=self.copy_password)
        copy_btn.grid(row=0, column=1, padx=10)

    def generate_random_password(self):
        self.password_entry_box.delete(0, END)
        try:
            password_length = int(self.length_entry_box.get())
            self.feedback.destroy() # Destroy feedback if length is there
            data = UPPERCASE+LOWERCASE+NUMBER + SYMBOLS
            password = ''.join(choice(data) for _ in range(password_length))
            self.password_entry_box.insert(0, password)
        except ValueError:
            self.feedback = Label(self.window, fg="red",
                                  text="Please enter number of characters")
            self.feedback.place(x=130, y=100)

    def copy_password(self):
        self.window.clipboard_clear()
        self.window.clipboard_append(self.password_entry_box.get())

if __name__ == ' __main__':
    PasswordGenerator().window.mainloop()

*Output Screenshots *

Conclusion

In this part, we've created a Password Generator. In the upcoming part, we'll be creating a Password Manager which will be able to store our password, that too with encryption, in a SQL database. We'll also integrate this Password Generator inside that application. So, stay tuned!

16