DEV Community

Pratik Pathak
Pratik Pathak

Posted on • Originally published at pratikpathak.com on

Create an Interactive command line tool in Python 🐍

Creative an interactive in Python is very easy, there are many packages available that can help you to achieve this task. One such tool is Pyinquirer. Let’s learn about building a Python command line tool using Pyinquirer…

Let’s start building the Project

For Package Management🏢 we are going to use Poetry, Don’t know how to use poetry learn it from here https://pratikpathak.com/python-poetry-example/.

We are going to build a simple command line tool, which gives an interactive menu of list of wifi passwords and when the user selects one option it will show the wifi password.

Create a Commandline Python project by using Poetry Python

Poetry can create a Boilerplate template for your project, you just need to use poetry new the command to create a new project. By using this command poetry will create all the necessary files required in a project.

poetry new wifiPwd
Enter fullscreen mode Exit fullscreen mode

This command will create a folder named wifiPwd and inside the folder, you will see a list of files, we will go through each of them individually.

The folder structure looks like this:

D:\PROJECTS\WIFIPWD
│ pyproject.toml
│ README.md
│
├───tests
│ __init__.py
│
└───wifipwd
        __init__.py
Enter fullscreen mode Exit fullscreen mode

Tip! : You can use the “Tree” command to view the folder structure

Creating the Driver Code main.py

Let’s create a Python file named “main.py” in the root folder. The project entry point will be from here. Before writing the code let’s install all required packages beforehand.

We will use “PyInquirer” to create an interactive terminal. let’s install PyInquirer using poetry add command.

Install Packages using Poetry Add Command

poetry add pyinquirer
Enter fullscreen mode Exit fullscreen mode

This command will fetch the PyPi registry, download the packages from here, and install it in your system. This will also update the pyproject.toml file, it will add Pyinquirer into dependencies.

Now we need a tool for formatting Python code. We will use the “Black” package for formatting our code. But this is not mandatory for the project, it’s a dev dependency, We want to format the code for us easily, it has no purpose in production which’s why it’s a dev dependency

Install Dev Package using Poetry Add Command

poetry add black --group dev
Enter fullscreen mode Exit fullscreen mode

First thing first, Step 0 of our program will be to run the command.

poetry install
Enter fullscreen mode Exit fullscreen mode

This will validate the pyproject.toml file, and then it will install all the dependencies in the file. After running “poetry install” you will see output something like this

Creating virtualenv wifipwd-s1RAI5FV-py3.9 in C:\Users\pratik\AppData\Local\pypoetry\Cache\virtualenvs
Resolving dependencies... (0.1s)

Installing the current project: wifipwd (0.1.0)
Enter fullscreen mode Exit fullscreen mode

Did you notice? It says “Installing the current project: wifipwd (0.1.0)”, what does it mean?

It means Poetry is treating the whole project as a package. Now you can use import wifipwd it to import the project functionality directly.

Final pyproject.toml will look something like this –

[tool.poetry]
name = "wifipwd"
version = "0.1.0"
description = ""
authors = ["Pratik Pathak <pratikpathak200@gmail.com>"]
readme = "README.md"

[tool.poetry.dependencies]
python = "^3.9"
pyinquirer = "^1.0.3"

[tool.poetry.group.dev.dependencies]
black = "^23.12.1"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

Enter fullscreen mode Exit fullscreen mode

Now let’s go back to main.py file…

Here we have to take input from the user in our example wifi name, and then we will just show the output.

How to Interactively take input from commandline python?

You can easily create an interactive menu using Pyinquirer first lets get list all saved wifi password.

You can get the list of saved wifi passwords by using

import subprocess

data = (
    subprocess.check_output(["netsh", "wlan", "show", "profiles"])
    .decode("utf-8")
    .split("\n")
)
profiles = [i.split(":")[1][1:-1] for i in data if "All User Profile" in i]
Enter fullscreen mode Exit fullscreen mode

the list “profile” consist all the wifi names. Let’s go on and create an interactive menu using Pyinuirer

from PyInquirer import prompt

question = [
    {
        "type": "list",
        "name": "wifi",
        "message": "Choose the wifi whose password you want to see",
        "choices": profiles,
    }
]
answer = prompt(question)
wifiName = answer["wifi"]
Enter fullscreen mode Exit fullscreen mode

Now we have got the wifi name in “wifiName” variable, now the only thing remain is to create a function which returns the password.

The main.py file will look something like this

import subprocess
from PyInquirer import prompt
from wifipwd import wifiPassword

data = (
    subprocess.check_output(["netsh", "wlan", "show", "profiles"])
    .decode("utf-8")
    .split("\n")
)
profiles = [i.split(":")[1][1:-1] for i in data if "All User Profile" in i]

question = [
    {
        "type": "list",
        "name": "wifi",
        "message": "Choose the wifi whose password you want to see",
        "choices": profiles,
    }
]
answer = prompt(question)
wifiName = answer["wifi"]
results = wifiPassword(wifiName)

try:
    print("{:<30}| \033[92m{:<}\033[00m".format(wifiName, results))
except IndexError:
    print("{:<30}| {:<}".format(wifiName, ""))
Enter fullscreen mode Exit fullscreen mode

Did you notice? we used “from wifipwd import wifiPassword”, we are treating the whole project like a package, so let’s write the “wifiPassword” function. wifiPassword function will be located at “wifipwd > __init__.py”.

Now we will add wifiPassword() function, Lets edit “wifipwd > __init__.py”, the final “__init__.py” will look like

import subprocess

def wifiPassword(name):
    try:
        results = (
            subprocess.check_output(
                ["netsh", "wlan", "show", "profile", name, "key=clear"]
            )
            .decode("utf-8")
            .split("\n")
        )
    except subprocess.CalledProcessError:
        print("{:<30}| {:<}".format(name, "ENCODING ERROR"))

    results = [b.split(":")[1][1:-1] for b in results if "Key Content" in b]
    try:
        return results[0]
    except IndexError:
        return ""
Enter fullscreen mode Exit fullscreen mode

The Project is Almost completed. The last step will be to format the code. We have already installed Black python package for code formatting, Let’s format our code using black.

How to format code using Black Python formatter?

It’s very easy to format our code using “Black” just run the below command.

black main.py
Enter fullscreen mode Exit fullscreen mode

Pro Tip!: You can also format the whole folder by providing the folder name for example.

black wifipwd
Enter fullscreen mode Exit fullscreen mode

You will get output something like this

All done! ✨ 🍰 ✨
1 file reformatted.
Enter fullscreen mode Exit fullscreen mode

Note: If you get any error make sure you are inside a virtual environment, use “poetry shell” to activate the virtual environment, if it still not working update the black by using “poetry add black@latest”

That’s it!

You are done. You have successfully created a Python Command line tool, which is also packaged together using poetry.

Top comments (0)