{ "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "
\n", "\n", "
\n", "\"Unidata\n", "
\n", "\n", "

Command Line Tool Creation

\n", "

Unidata Python Workshop

\n", "\n", "
\n", "
\n", "\n", "
\n", "\n", "
\"Command
\n", "\n", "\n", "## Overview:\n", "\n", "* **Teaching:** 30 minutes\n", "* **Exercises:** 36 minutes" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Create command line tools to do common jobs\n", "* Do common data manipulations\n", "* Make plots\n", "* Download data or batch process items\n", "\n", "
\"Sounding\"
" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# You are already used to using command line tools\n", "* ls\n", "* grep\n", "* git\n", "* GEMPAK" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Command line tools take command line arguments\n", "\n", "```\n", "GREP(1) BSD General Commands Manual GREP(1)\n", "\n", "NAME\n", " grep, egrep, fgrep, zgrep, zegrep, zfgrep -- file pattern searcher\n", "\n", "SYNOPSIS\n", " grep [-abcdDEFGHhIiJLlmnOopqRSsUVvwxZ] [-A num] [-B num] [-C[num]] [-e pattern] [-f file] [--binary-files=value] [--color[=when]] [--colour[=when]]\n", " [--context[=num]] [--label] [--line-buffered] [--null] [pattern] [file ...]\n", "\n", "DESCRIPTION\n", " The grep utility searches any given input files, selecting lines that match one or more patterns. By default, a pattern matches an input line if the regular\n", " expression (RE) in the pattern matches the input line without its trailing newline. An empty expression matches every line. Each input line that matches at\n", " least one of the patterns is written to the standard output.\n", "\n", " grep is used for simple patterns and basic regular expressions (BREs); egrep can handle extended regular expressions (EREs). See re_format(7) for more informa-\n", " tion on regular expressions. fgrep is quicker than both grep and egrep, but can only handle fixed patterns (i.e. it does not interpret regular expressions).\n", " Patterns may consist of one or more lines, allowing any of the pattern lines to match a portion of the input.\n", "\n", " zgrep, zegrep, and zfgrep act like grep, egrep, and fgrep, respectively, but accept input files compressed with the compress(1) or gzip(1) compression utili-\n", " ties.\n", "\n", " The following options are available:\n", "\n", " -A num, --after-context=num\n", " Print num lines of trailing context after each match. See also the -B and -C options.\n", "\n", " -a, --text\n", " Treat all files as ASCII text. Normally grep will simply print ``Binary file ... matches'' if files contain binary characters. Use of this option\n", " forces grep to output lines matching the specified pattern.\n", "\n", " -B num, --before-context=num\n", " Print num lines of leading context before each match. See also the -A and -C options.\n", "\n", " -b, --byte-offset\n", " The offset in bytes of a matched pattern is displayed in front of the respective matched line.\n", "\n", " -C[num, --context=num]\n", " Print num lines of leading and trailing context surrounding each match. The default is 2 and is equivalent to -A 2 -B 2. Note: no whitespace may be\n", " given between the option and its argument.\n", "```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Start by writing a \"requirements document\" for yourself\n", "\n", "* Describe the specific functionality of the tool\n", "* Describe the options that are available to the user\n", "* Include an expected set of outputs" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## You can also begin the design process\n", "* Functional blocks\n", "* Flow charts\n", "* Interface decisions" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Let's design a tool to make a plot like this\n", "\n", "![Example image](example_output.png)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Requirements - Let's design the tool\n", "* Plot super national visible satellite image\n", "* Contour a recent GFS field of the user's choice and a level specified by the user\n", "* Plot with a basemap containing coastlines, country, state, and provice borders\n", "* Make the plot for the current time or up to 24 hours in the past\n", "* Use the GFS and satellite data from the time closest to that requested (smallest delta t)\n", "* Indicate the model and satellite times on the plot\n", "* Show or save the output image\n", "* Have a sensible default behavior\n", "* Include help documentation to remind others and ourselves how to use the program" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# We'll use five command line arguments\n", "\n", "* **--gfsfield GFSFIELD** - *CF field name of data to contour from the GFS model.*\n", "* **--gfslevel GFSLEVEL** - *Model level to plot (in hPa)*\n", "* **--hours HOURS** - *Time to plot (must be present or past)*\n", "* **--savefig** - *Save out figure instead of displaying it*\n", "* **--imgformat IMGFORMAT** - *Format to save the resulting image as.*" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# We could write a parser ourselves, but there's no need\n", "\n", "The [argparse](https://docs.python.org/3/library/argparse.html) module has us covered!\n", "![](http://i.imgur.com/KGrV41o.png)" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true, "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "# For demo purposes only\n", "import sys\n", "sys.argv = ['greetme.py', '--name', 'John', '--greeting', 'Hola,']" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": true, "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "import argparse\n", "\n", "# Create an instance\n", "parser = argparse.ArgumentParser(description='A simple program that prints a greeting to the name specified')" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/plain": [ "_StoreAction(option_strings=['--greeting'], dest='greeting', nargs=None, const=None, default='Hello, ', type=, choices=None, help='Greeting to be used', metavar=None)" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Add a name argument\n", "parser.add_argument('--name', type=str, required=True, help='Name of the person being greeted')\n", "\n", "parser.add_argument('--greeting', type=str, default='Hello, ', help='Greeting to be used')" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "# Parse the arguments\n", "args = parser.parse_args()" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hola, John\n" ] } ], "source": [ "# Print the greeting\n", "print('{} {}'.format(args.greeting, args.name))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Let's run it all together!\n", "\n", "* Create using the editor in the notebook\n", "* Run from the command line" ] } ], "metadata": { "celltoolbar": "Slideshow", "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.2" } }, "nbformat": 4, "nbformat_minor": 2 }