Sunday, October 5, 2025

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 Module
Picture by Writer | Ideogram

 

Introduction

 
I’m certain most of you’ve gotten used a command shell sooner or later. In case you haven’t, whereas it might look boring in comparison with a GUI, a command-line interface (CLI) could be very light-weight and provides you rather 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 underneath the hood—belongings you usually use each 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 steadily including instructions, assist, fundamental validation, aliases, and pleasant output. The one requirement out of your aspect is to have a fundamental familiarity with Python capabilities and courses. 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 suggests it processes one command at a time. It additionally takes care of studying enter through 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 remainder—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 checklist instructions.n"
    immediate = "(myshell) "

    def do_greet(self, arg):
        """Greet the named individual: greet """
        identify = arg.strip() or "stranger"
        print(f"Howdy, {identify}!")

    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 attempt 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 checklist instructions.
(myshell) assist

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

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

(myshell) greet kanwal
Howdy, kanwal!

(myshell) exit
Goodbye!

 

 

// Step 2: Parsing Arguments Cleanly

For extra complicated instructions that require a number of enter values—comparable to including or multiplying—you will have 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 checklist instructions.n"
    immediate = "(myshell) "

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

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

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

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

 
Now, let’s give it a attempt:

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

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

(myshell) add 2450 3456 8904 3467 
Sum = 18277.0

(myshell) exit
Goodbye!

 

// Step 3: Including a Assist System

We have now already seen one assist command above. That’s the default one which the cmd module creates robotically. It reveals the strategy docstrings. You can even add customized assist for a command or subject like this:

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

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

    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 checklist instructions.")
        print("  - Use 'assist ' for particulars.")
        print("  - Arguments help quotes (through shlex).")

 

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

(myshell) assist
Documented instructions (sort assist ):
========================================
exit  greet
Undocumented instructions:
======================
assist
Fundamentals:
  - Use 'assist' or '?' to checklist instructions.
  - Use 'assist ' for particulars.
  - Arguments help quotes (through 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() methodology to intercept unknown instructions. You can even use emptyline() to regulate what occurs when the consumer 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 checklist 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 (sort assist ):
========================================
exit  assist

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

 

// Step 5: Including Command Aliases

Aliases are quick names. Tons of my pals 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() methodology. 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",
        "whats up": "greet",
        "sum": "add",
    }

    def precmd(self, line: str) -> str:
        # Normalize/therapeutic massage enter earlier than dispatch
        components = line.strip().cut up(maxsplit=1)
        if not components:
            return line
        cmd_name = components[0]
        relaxation = components[1] if len(components) > 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 """
        identify = arg.strip() or "stranger"
        print(f"Howdy, {identify}!")

    def do_add(self, arg):
        """Add numbers: add 1 2 3"""
        attempt:
            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 (sort 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 checklist instructions."
    immediate = "(myshell) "

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

    # ----- Enter processing -----
    def precmd(self, line):
        components = line.strip().cut up(maxsplit=1)
        if not components:
            return line
        cmd_name = components[0]
        relaxation = components[1] if len(components) > 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 checklist instructions.")

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

    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"""
        attempt:
            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 sort: 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 checklist 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 checklist instructions.
(myshell) whats up
Howdy, stranger!
(myshell) WRONG COMMAND
Unknown command: 'WRONG COMMAND'. Sort 'assist' to checklist instructions.
(myshell) echo KDnuggets is a superb web site
KDnuggets is a superb web site
(myshell) exit
Goodbye!

 

Wrapping Up

 
You simply realized the right way to construct an interactive shell utilizing the cmd module with none exterior dependencies. Isn’t that tremendous?

Earlier than we end, it’s price mentioning just a few widespread pitfalls to be careful for: First, forgetting to return True in your exit command will forestall the shell loop from ending. Second, counting on easy whitespace splitting for arguments may cause issues when customers enter quoted textual content, so utilizing shlex is advisable. Lastly, not dealing with the emptyline() methodology correctly can result in sudden conduct, like repeating the final command when the consumer 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 may wish 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 medication. She co-authored the e-book “Maximizing Productiveness with ChatGPT”. As a Google Era Scholar 2022 for APAC, she champions variety 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

Latest Articles

PHP Code Snippets Powered By : XYZScripts.com