Upgrade to Pro — share decks privately, control downloads, hide ads and more …

FOSSCON 2015 - Writing Better Command Line Applications with Python

FOSSCON 2015 - Writing Better Command Line Applications with Python

Often the first step in automating a repetitive task is to write a command line script. Python is a great language for this because of the number of modules and packages available -- but all of the options can be overwhelming or seem like overkill. This talk will cover many of the useful Python tools available for writing command line applications and when and why you might want to use each.

Dave Forgac

August 22, 2015
Tweet

More Decks by Dave Forgac

Other Decks in Technology

Transcript

  1. Execute or Import def main(): pass # do stuff here

    if __name__ == '__main__': main()
  2. hello_argparse.py import argparse def hello(): """ Argparse CLI to greet

    the provided NAME. """ parser = argparse.ArgumentParser() parser.add_argument('name', help="name of person to greet") parser.add_argument('-c', '--count', type=int, default=1, help="number of times to print the greeting") args = parser.parse_args() for i in xrange(args.count): print("Hello, {0}!".format(args.name))
  3. hello-argparse --help $ hello-argparse --help usage: hello-argparse [-h] [-c COUNT]

    name positional arguments: name name of person to greet optional arguments: -h, --help show this help message and exit -c COUNT, --count COUNT number of times to print the greeting
  4. hello-argparse $ hello-argparse usage: hello-argparse [-h] [-c COUNT] name hello-argparse:

    error: too few arguments $ hello-argparse FOSSCON Hello, FOSSCON! $ hello-argparse --count 3 FOSSCON Hello, FOSSCON! Hello, FOSSCON! Hello, FOSSCON!
  5. First: Decorators def wrapper(func): # wraps a function in order

    to add additional behavior @wrapper def my_function(example_arg): # does stuff
  6. hello_click.py import click @click.command() @click.argument('name') @click.option('--count', '-c', default=1, help="Number of

    times to print the greeting") def hello(name, count): """ Click CLI to greet the provided NAME. """ for i in xrange(count): print("Hello, {0}!".format(name))
  7. hello-click --help $ hello-click --help Usage: hello-click [OPTIONS] NAME Click

    CLI to greet the provided NAME. Options: -c, --count INTEGER Number of times to print the greeting --help Show this message and exit.
  8. hello-click $ hello-click Usage: hello-click [OPTIONS] NAME Error: Missing argument

    "name". $ hello-click FOSSCON Hello, FOSSCON! $ hello-click --count 3 FOSSCON Hello, FOSSCON! Hello, FOSSCON! Hello, FOSSCON!
  9. A better CLI app! Read from a file or stdin

    Write to a file or stdout Update to log or stderr Has an option or two Has colors! Does something
  10. cli_click.py @click.command() @click.argument('infile', type=click.File('r'), default='-') @click.argument('outfile', type=click.File('w'), default='-') @click.option('--log-file', '-l',

    type=click.File('w'), default=sys.stderr) @click.option('--verbose', '-v', is_flag=True) def cli(infile, outfile, log_file, verbose): """ Count the occurances of characters in INFILE and output to OUTFILE. """ …
  11. cli_click.py (cont'd) … if verbose: click.secho("Infile: {0}".format(infile), file=log_file) click.secho("Outfile: {0}".format(outfile),

    file=log_file) text = infile.read() char_counts = Counter(text) output = json.dumps(dict(char_counts.most_common()), indent=2) click.secho("Counted characters.", bold=True, file=log_file) click.secho(output, file=outfile, fg='green')
  12. fosscon-click --help $ fosscon-click --help Usage: fosscon-click [OPTIONS] [INFILE] [OUTFILE]

    Count the occurances of characters in INFILE and output to OUTFILE. Options: -l, --log-file FILENAME -v, --verbose --help Show this message and exit.
  13. File input, stdout output $ fosscon-click data/declaration.txt Counted characters... {

    "\n": 176, " ": 1706, "'": 1, "-": 3, ",": 104, ".": 37, "1": 1, "4": 1, …
  14. stdin input, file output $ echo "testing" | fosscon-click -

    outfile.txt Counted characters... $ cat outfile.txt { "e": 1, "g": 1, "i": 1, "\n": 1, "n": 1, "s": 1, "t": 2 }
  15. Verbose with log file $ echo "testing" | fosscon-click --verbose

    --log-file log.txt - out.txt $ cat log.txt Infile: <_io.TextIOWrapper name='<stdin>' encoding='utf-8'> Outfile: <unopened file 'outfile.txt' w> Counted characters...