Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a shell command line application with Python and Click

I'm using click (http://click.pocoo.org/3/) to create a command line application, but I don't know how to create a shell for this application.
Suppose I'm writing a program called test and I have commands called subtest1 and subtest2

I was able to make it work from terminal like:

$ test subtest1
$ test subtest2

But what I was thinking about is a shell, so I could do:

$ test  
>> subtest1  
>> subtest2

Is this possible with click?

like image 304
Fábio Clug Avatar asked Mar 11 '15 15:03

Fábio Clug


People also ask

How do you write a shell command in Python?

If you need to execute a shell command with Python, there are two ways. You can either use the subprocess module or the RunShellCommand() function. The first option is easier to run one line of code and then exit, but it isn't as flexible when using arguments or producing text output.

Can I use Python to execute shell commands?

The os module in Python includes functionality to communicate with the operating system. It is one of the standard utility modules of Python. It also offers a convenient way to use operating system-dependent features, shell commands can be executed using the system() method in the os module.


1 Answers

There is now a library called click_repl that does most of the work for you. Thought I'd share my efforts in getting this to work.

The one difficulty is that you have to make a specific command the repl command, but we can repurpose @fpbhb's approach to allow calling that command by default if another one isn't provided.

This is a fully working example that supports all click options, with command history, as well as being able to call commands directly without entering the REPL:

import click
import click_repl
import os
from prompt_toolkit.history import FileHistory

@click.group(invoke_without_command=True)
@click.pass_context
def cli(ctx):
    """Pleasantries CLI"""
    if ctx.invoked_subcommand is None:
        ctx.invoke(repl)

@cli.command()
@click.option('--name', default='world')
def hello(name):
    """Say hello"""
    click.echo('Hello, {}!'.format(name))

@cli.command()
@click.option('--name', default='moon')
def goodnight(name):
    """Say goodnight"""
    click.echo('Goodnight, {}.'.format(name))

@cli.command()
def repl():
    """Start an interactive session"""
    prompt_kwargs = {
        'history': FileHistory(os.path.expanduser('~/.repl_history'))
    }
    click_repl.repl(click.get_current_context(), prompt_kwargs=prompt_kwargs)

if __name__ == '__main__':
    cli(obj={})

Here's what it looks like to use the REPL:

$ python pleasantries.py
> hello
Hello, world!
> goodnight --name fpbhb
Goodnight, fpbhb.

And to use the command line subcommands directly:

$ python pleasntries.py goodnight
Goodnight, moon.
like image 189
theazureshadow Avatar answered Oct 07 '22 10:10

theazureshadow