10

I want to create an interactive shell type application. For example:

> ./app.py

Enter a command to do something. eg `create name price`. 
For to get help, enter "help" (without quotes)

> create item1 10
Created "item1", cost $10

> del item1
Deleted item1

> exit 
...

I could of course use a infinte loop getting user input, splitting the line to get the individual parts of the command, but is there a better way? Even in PHP (Symfony 2 Console) they allow you to create console commands to help setup web applications for example. Is there something like that in Python (I am using Python 3)

Jiew Meng
  • 84,767
  • 185
  • 495
  • 805

3 Answers3

16

Just input the commands in a loop.

For parsing the input, shlex.split is a nice option. Or just go with plain str.split.

import readline
import shlex

print('Enter a command to do something, e.g. `create name price`.')
print('To get help, enter `help`.')

while True:
    cmd, *args = shlex.split(input('> '))

    if cmd=='exit':
        break

    elif cmd=='help':
        print('...')

    elif cmd=='create':
        name, cost = args
        cost = int(cost)
        # ...
        print('Created "{}", cost ${}'.format(name, cost))

    # ...

    else:
        print('Unknown command: {}'.format(cmd))

The readline library adds history functionality (up arrow) and more. Python interactive shell uses it.

Oleh Prypin
  • 33,184
  • 10
  • 89
  • 99
  • I don't suppose you'd be willing to annotate your answer to indicate it is Python 3. I know the question says this, but some of us jump to answers after reading the title of the question. I just tripped on this for a bit since both the *args and the input vs raw_input features are new to me. – sage Mar 29 '14 at 15:26
  • 1
    @sage It's your problem that you use an old version of Python. I don't think it should be indicated that I use a fresh version of something, not vice-versa as you think. Also, there is even the tag [[tag:python-3.x]]. Also, modifying it for Python 2.7 is rather trivial. – Oleh Prypin Mar 29 '14 at 15:32
  • I could not agree more that you have no obligation to comment that you are not using the older version. And modifying it was easy. Neither of those things change that the small comment would have made your answer more useful to more people; at this point, our comments do the same thing. Searching recent news, I was surprised how many people have not migrated - in fact, I was even more surprised to realize how long it has now been that Python 3 has been available. I guess I'm overdue for migrating... – sage Apr 02 '14 at 19:51
10

Another approach to building interactive applications like this is by using the cmd module.

# app.py
from cmd import Cmd

class MyCmd(Cmd):

    prompt = "> "

    def do_create(self, args):
        name, cost = args.rsplit(" ", 1) # args is string of input after create
        print('Created "{}", cost ${}'.format(name, cost))

    def do_del(self, name):
        print('Deleted {}'.format(name))

    def do_exit(self, args):
        raise SystemExit()

if __name__ == "__main__":

    app = MyCmd()
    app.cmdloop('Enter a command to do something. eg `create name price`.')

And here is the output of running the above code (if the above code was in a file named app.py):

$ python app.py
Enter a command to do something. eg `create name price`.
> create item1 10
Created "item1", cost $10
> del item1
Deleted item1
> exit
$
Jaymon
  • 5,363
  • 3
  • 34
  • 34
0

You could start by having a look at argparse.

It does not provide a complete interactive shell, like you ask, but it helps in creating functionality similar to your PHP example.

Teun Zengerink
  • 4,277
  • 5
  • 30
  • 32
  • 2
    Yes, I saw that, the main problem is it runs once and quits. I need something that is "interactive". Thanks though – Jiew Meng Feb 18 '12 at 10:43