HomeArtificial IntelligenceNewbie’s Information to Creating Your Personal Python Shell with the cmd Module

Newbie’s Information to Creating Your Personal Python Shell with the cmd Module


Newbie’s Information to Creating Your Personal Python Shell with the cmd ModuleNewbie’s Information to Creating Your Personal Python Shell with the cmd Module
Picture by Creator | Ideogram

 

Introduction

 
I’m certain most of you might have used a command shell in some unspecified time in the future. In the event you haven’t, whereas it could look boring in comparison with a GUI, a command-line interface (CLI) may be very light-weight and provides you way more management. Some widespread examples are SQLite, Git, and the Python REPL. On this tutorial, we’ll discover ways to use Python’s cmd module to construct our personal interactive shell with none exterior dependencies. It’s quite simple and intuitive to get began. Engaged on initiatives like this helps you perceive how issues work below the hood—belongings you usually use day by day however don’t suppose a lot about. It’s additionally helpful in case you ever plan to construct admin consoles in your purposes.

We’ll construct our shell in small chunks, beginning with a minimal instance after which regularly including instructions, assist, fundamental validation, aliases, and pleasant output. The one requirement out of your facet is to have a fundamental familiarity with Python capabilities and lessons. So, let’s get began.

 

Step-by-Step Course of to Construct Your Personal Python Shell

 
Let’s have a fast overview of the cmd module, since we’ve already used it however haven’t defined what it’s. It offers a base class (cmd.Cmd) to construct line-oriented command interpreters, which implies it processes one command at a time. It additionally takes care of studying enter by way of a immediate, command dispatch (mapping textual content to strategies), and the assistance system. You implement instructions by defining strategies named do_. The module handles the remaining—simple and easy.
 

// Step 1: Creating the Minimal Shell

Create a file referred to as myshell.py:

import cmd

class MyShell(cmd.Cmd):
    intro = "Welcome to MyShell! Sort assist or ? to listing instructions.n"
    immediate = "(myshell) "

    def do_greet(self, arg):
        """Greet the named particular person: greet """
        title = arg.strip() or "stranger"
        print(f"Good day, {title}!")

    def do_exit(self, arg):
        """Exit the shell."""
        print("Goodbye!")
        return True  # Returning True tells cmdloop() to exit

if __name__ == "__main__":
    MyShell().cmdloop()

 

Run the code utilizing:

 

Now, let’s strive just a few instructions. cmdloop() will begin the interactive loop, and we will work together as proven beneath:

Welcome to MyShell! Sort assist or ? to listing instructions.
(myshell) assist

Documented instructions (kind assist ):
========================================
exit  greet  assist

(myshell) ?
Documented instructions (kind assist ):
========================================
exit  greet  assist

(myshell) greet kanwal
Good day, kanwal!

(myshell) exit
Goodbye!

 

 

// Step 2: Parsing Arguments Cleanly

For extra advanced instructions that require a number of enter values—equivalent to including or multiplying—you’ll need one thing to parse areas, quotes, and so forth. For this, we’ll use shlex.cut up. Let’s check out the instance code:

import cmd
import shlex

class MyShell(cmd.Cmd):
    intro = "Welcome to MyShell! Sort assist or ? to listing instructions.n"
    immediate = "(myshell) "

    def do_add(self, arg):
        """Add numbers: add 1 2 3"""
        strive:
            elements = shlex.cut up(arg)
            nums = [float(p) for p in parts]
        besides ValueError:
            print("Error: all arguments have to be numbers.")
            return
        besides Exception as e:
            print(f"Parse error: {e}")
            return

        complete = sum(nums)
        print(f"Sum = {complete}")

    def do_exit(self, arg):
        """Exit the shell."""
        print("Goodbye!")
        return True

if __name__ == "__main__":
    MyShell().cmdloop()

 
Now, let’s give it a strive:

Welcome to MyShell! Sort assist or ? to listing instructions.

(myshell) ?
Documented instructions (kind assist ):
========================================
add  exit  assist

(myshell) add 2450 3456 8904 3467 
Sum = 18277.0

(myshell) exit
Goodbye!

 

// Step 3: Including a Assist System

Now we have already seen one assist command above. That’s the default one which the cmd module creates routinely. It exhibits the strategy docstrings. You may also add customized assist for a command or matter like this:

class MyShell(cmd.Cmd):
    intro = "Welcome to MyShell! Sort assist or ? to listing instructions.n"
    immediate = "(myshell) "

    def do_greet(self, arg):
        """Greet somebody. Utilization: greet """
        title = arg.strip() or "stranger"
        print(f"Good day, {title}!")

    def help_greet(self):
        print("greet ")
        print("  Prints a pleasant greeting.")
        print("  Instance: greet Alice")

    def do_exit(self, arg):
        """Exit the shell."""
        print("Goodbye!")
        return True

    def do_help(self, arg):
        # Preserve default conduct, however present a tiny information when no arg
        if arg:
            return tremendous().do_help(arg)
        tremendous().do_help(arg)
        print()
        print("Fundamentals:")
        print("  - Use 'assist' or '?' to listing instructions.")
        print("  - Use 'assist ' for particulars.")
        print("  - Arguments help quotes (by way of shlex).")

 

Welcome to MyShell! Sort assist or ? to listing instructions.

(myshell) assist
Documented instructions (kind assist ):
========================================
exit  greet
Undocumented instructions:
======================
assist
Fundamentals:
  - Use 'assist' or '?' to listing instructions.
  - Use 'assist ' for particulars.
  - Arguments help quotes (by way of shlex).
  
(myshell) assist greet
greet 
  Prints a pleasant greeting.
  Instance: greet Alice
  
(myshell) assist exit
Exit the shell.

(myshell) exit
Goodbye!

 

// Step 4: Dealing with Errors and Unknown Instructions

We are able to override the default() technique to intercept unknown instructions. You may also use emptyline() to regulate what occurs when the person presses Enter with no enter. Let’s make the shell do nothing if no enter has been entered:

class MyShell(cmd.Cmd):
    immediate = "(myshell) "

    def default(self, line):
        print(f"Unknown command: {line!r}. Sort 'assist' to listing instructions.")

    def emptyline(self):
        # By default, urgent Enter repeats the final command. Override to do nothing.
        cross

    def do_exit(self, arg):
        """Exit the shell."""
        print("Goodbye!")
        return True

 

(myshell) assist

Documented instructions (kind assist ):
========================================
exit  assist

(myshell) 
(myshell) 
(myshell) exit
Goodbye!

 

// Step 5: Including Command Aliases

Aliases are quick names. Tons of my mates have aliases as effectively, particularly these with the identical names. Equally, you need to use a shorter—and simpler to recollect—model of instructions by implementing aliases within the precmd() technique. Right here’s how you are able to do this:

import shlex
import cmd

class MyShell(cmd.Cmd):
    immediate = "(myshell) "
    aliases = {
        "give up": "exit",
        "q": "exit",
        "hey": "greet",
        "sum": "add",
    }

    def precmd(self, line: str) -> str:
        # Normalize/therapeutic massage enter earlier than dispatch
        elements = line.strip().cut up(maxsplit=1)
        if not elements:
            return line
        cmd_name = elements[0]
        relaxation = elements[1] if len(elements) > 1 else ""
        if cmd_name in self.aliases:
            cmd_name = self.aliases[cmd_name]
        return f"{cmd_name} {relaxation}".strip()

    # Outline instructions used above
    def do_greet(self, arg):
        """Greet somebody. Utilization: greet """
        title = arg.strip() or "stranger"
        print(f"Good day, {title}!")

    def do_add(self, arg):
        """Add numbers: add 1 2 3"""
        strive:
            nums = [float(x) for x in shlex.split(arg)]
        besides Exception:
            print("Utilization: add  [ ...]")
            return
        print(f"Sum = {sum(nums)}")

    def do_exit(self, arg):
        """Exit the shell."""
        print("Goodbye!")
        return True

 

(myshell) ?
Documented instructions (kind assist ):
========================================
add  exit  greet  assist

(myshell) sum 2 3 4
Sum = 9.0

(myshell) add 2 3 4
Sum = 9.0

(myshell) q
Goodbye!

 

// Step 6: Placing It All Collectively

import cmd
import shlex

class MyShell(cmd.Cmd):
    intro = "Welcome to MyShell! Sort assist or ? to listing instructions."
    immediate = "(myshell) "

    # Easy aliases
    aliases = {"q": "exit", "give up": "exit", "hey": "greet", "sum": "add"}

    # ----- Enter processing -----
    def precmd(self, line):
        elements = line.strip().cut up(maxsplit=1)
        if not elements:
            return line
        cmd_name = elements[0]
        relaxation = elements[1] if len(elements) > 1 else ""
        if cmd_name in self.aliases:
            cmd_name = self.aliases[cmd_name]
        return f"{cmd_name} {relaxation}".strip()

    def emptyline(self):
        # Do nothing on empty line
        cross

    def default(self, line):
        print(f"Unknown command: {line!r}. Sort 'assist' to listing instructions.")

    # ----- Instructions -----
    def do_greet(self, arg):
        """Greet somebody. Utilization: greet """
        title = arg.strip() or "stranger"
        print(f"Good day, {title}!")

    def help_greet(self):
        print("greet ")
        print("  Prints a pleasant greeting.")
        print("  Instance: greet Alice")

    def do_add(self, arg):
        """Add numbers: add 1 2 3"""
        strive:
            nums = [float(x) for x in shlex.split(arg)]
        besides Exception:
            print("Utilization: add  [ ...]")
            return
        print(f"Sum = {sum(nums)}")

    def do_echo(self, arg):
        """Echo again what you kind: echo """
        print(arg)

    def do_exit(self, arg):
        """Exit the shell."""
        print("Goodbye!")
        return True

    # ----- Assist tweaks -----
    def do_help(self, arg):
        if arg:
            return tremendous().do_help(arg)
        tremendous().do_help(arg)
        print()
        print("Fundamentals:")
        print("  - Use 'assist' or '?' to listing instructions.")
        print("  - Use 'assist ' for particulars.")
        print('  - Quotes are supported in arguments (e.g., add "3.5" 2).')

if __name__ == "__main__":
    MyShell().cmdloop()

 

Welcome to MyShell! Sort assist or ? to listing instructions.
(myshell) hey
Good day, stranger!
(myshell) WRONG COMMAND
Unknown command: 'WRONG COMMAND'. Sort 'assist' to listing instructions.
(myshell) echo KDnuggets is a superb web site
KDnuggets is a superb web site
(myshell) exit
Goodbye!

 

Wrapping Up

 
You simply realized tips on how to construct an interactive shell utilizing the cmd module with none exterior dependencies. Isn’t that incredible?

Earlier than we end, it’s price declaring just a few widespread pitfalls to be careful for: First, forgetting to return True in your exit command will stop the shell loop from ending. Second, counting on easy whitespace splitting for arguments could cause issues when customers enter quoted textual content, so utilizing shlex is advisable. Lastly, not dealing with the emptyline() technique correctly can result in surprising conduct, like repeating the final command when the person presses Enter on an empty line.

I might love to listen to your ideas about this text within the feedback part, in addition to any concepts you would possibly need to discover additional.
 
 

Kanwal Mehreen is a machine studying engineer and a technical author with a profound ardour for information science and the intersection of AI with drugs. She co-authored the book “Maximizing Productiveness with ChatGPT”. As a Google Era Scholar 2022 for APAC, she champions range and educational excellence. She’s additionally acknowledged as a Teradata Range in Tech Scholar, Mitacs Globalink Analysis Scholar, and Harvard WeCode Scholar. Kanwal is an ardent advocate for change, having based FEMCodes to empower ladies in STEM fields.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments