Parsing arguments - first hack

Where have I been? #

It’s been a while since I posted up my progress to this blog, mostly for two reasons;

  1. I started Learn JavaScript The Hard Way and made reasonable progress through the first 19 exercises. This sister course of Zed’s follows a similar format so it was easy to adjust to.

  2. I spent way to long planning and implementing my game, which in retrospect was limiting my learning and not delivering anything new. I will return to the game in due course so I can get an online version up for closure.

In the meantime, I’ve progressed to Learn More Python The Hard Way instead. This book compliments the original text and actually prompts you to use your existing knowledge to produce useful little projects. Perhaps more importantly, it also offer insight into developer behaviours, avoiding typical blockers, overcoming procrastination and general good-coding advice and habits.

The first few exercises focus on creativity and a qualitative approach. Also, tidying your physical and virtual environments and creating a good set up, so you are not bogged down with admin tasks when you want to be letting your creative juices flow.

I found this really useful and dedicated some time to removing unnecessary applications (and distractions) from my laptops, fixed my virtual environments, set up repos and ensured my workspace was tidy and easily accessible. I also installed the Pop!_OS Linux distro onto an older Windows machine, so I could use it as my commuting machine and get more practice with Git synchronisation.

Command Line Arguments with Argparse #

The first coding challenge is this book is a hack to increase knowledge of command line arguments. Up to now I’d been using sys.argv which has limitations.

This challenge like many others in the book is time-boxed. The goal isn’t really to produce a final, production-standard tool, but to practising hacking, researching, and producing working code in a technical spike.

My first error here was that I went off and looked at the argparse tutorial in the Python docs. This in itself was not a bad thing, but I ran through the tutorial over a few hours and that wasn’t really the goal of the challenge.

So based on what I had learned, I approach the challenge again, limiting myself to two Pomodoro sessions (50 mins).

How did the challenge go? #

So with my knowledge of argparse, I started my timer, wrote my list of actions, converted that list to code comments and started to implement the comments.

I tried to implement one line at a time with frequent file execution. Two things became apparent very quickly:

  1. I kept writing JavaScript syntax into my Python script….
  2. My memory of argparse was terrible!

However, I did remember to import argparse and create a parser instance, even including a little description:

import argparse
# create a parser
parser = argparse.ArgumentParser(description="A little hack of argparse")
# at least two positional arguments
# at least three arguments that are optional
# additional positional args that are a list of files at the end of the file    
# arguments that can handle terminal wildcards

I then created a couple of optional argument as I remembered –help or -h was an optional argument from the tutorial. Providing help was one of the challenge requirements so that was one thing ticked off.

import argparse
# create a parser
parser = argparse.ArgumentParser(description="A little hack of argparse")
# at least two positional arguments
# at least three arguments that are optional
parser.add_argument("--opt1", help="first optional")
parser.add_argument("--opt2", help="second optional")
# additional positional args that are a list of files at the end of the file    
# arguments that can handle terminal wildcards

Then I ran the file from the command line to check for errors.

python using_argparse.py

Of course nothing happened but no errors were thrown, which was good. So I proceeded to add my positional arguments.

import argparse
# create a parser
parser = argparse.ArgumentParser(description="A little hack of argparse")
# at least two positional arguments
parser.add_argument("first", help="first argument") 
parser.add_argument("second", help="second argument")
# at least three arguments that are optional
parser.add_argument("--opt1", help="first optional")
parser.add_argument("--opt2", help="second optional")
# additional positional args that are a list of files at the end of the file    
# arguments that can handle terminal wildcards

I ran the script again, this time expecting to see an error due to missing the two positional arguments from the command.

Nothing.

I ran the script again using the –help optional argument I mentioned before.

Still nothing.

So I jumped back to the Python docs to see where I was going wrong. It soon became apparent. Even though I had created the parser and added arguments, I hadn’t given it any action! So I used parse_args() to create an instance of the parser and perform some printing action on it.

import argparse
# create a parser
parser = argparse.ArgumentParser(description="A little hack of argparse")
# at least two positional arguments
parser.add_argument("first", help="first argument") 
parser.add_argument("second", help="second argument")
# at least three arguments that are optional
parser.add_argument("--opt1", help="first optional")
parser.add_argument("--opt2", help="second optional")
# additional positional args that are a list of files at the end of the file    
# arguments that can handle terminal wildcards

args = parse_args()
if args:
    print("It works!")

Now when I ran the script with the –help argument, I got the generated output I was hoping for.
Screenshot 2018-11-29 at 18.36.08.png

Realising that I had totally forgotten the ‘action’ part of the script, I added some simple logic and called the arguments I had created, so i could test it a little more. (The else statement will never be run as error-handling will have kicked in!)

import argparse
# create a parser
parser = argparse.ArgumentParser(description="A little hack of argparse")
# at least two positional arguments
parser.add_argument("first", help="first argument") 
parser.add_argument("second", help="second argument")
# at least three arguments that are optional
parser.add_argument("--opt1", help="first optional")
parser.add_argument("--opt2", help="second optional")
# additional positional args that are a list of files at the end of the file    
# arguments that can handle terminal wildcards

args = parse_args()
if args.first:
    print("The first positional argument was applied")
if args.second:
    print("The second postional argument was applied")
else:
    print("No postional arguments applied.")

I could now test using the positional arguments, and produce errors when insufficient arguments were applied. (Shame I didn’t spot the typos!)

Screenshot 2018-11-29 at 18.44.45.png

This is good and I was getting somewhere.

PING! End of session. Time was up. Wow that went quick!

Time for review. What did I learn? #

The most obvious thing I realised was that I hadn’t written any pseudo code. Actually I hadn’t really progressed from writing Zed’s list of requirements, and turning those into actual things to do.

I should have written comments for things like:

# create instance of parser
# add logic for positional arguments

I ran out of time before I could consider the how to implement additional positional arguments that are a list of files at the end of the file and arguments that can handle terminal wildcards.

To be honest, I think it would have take another Pomodoro session of research just to get something basic up.

Study Drills #

There were three drills for this exercise that I have looked at since the clock stopped.

How many Python argument parsing libraries are there?

There are probably more by Argparse, Docopt, and Click seem to come up frequently when searching.

Then I found this great article comparing all three!

What’s the main advantage of argparse over sys.argv?

Although both are included in the standard library, argparse offers so much out of the box. It provides nice ‘help’ features and the error handling is also great.

Primarily, in my mind, sys.argv is a function for creating a list of arguments from the command line. Argparse is library for parsing from the command line and therefore is feature-rich.

What are things you can improve in your project starting method? Is there something you can eliminate now?

Not sure what Zed was getting at here. Maybe the help aspect of argparse, given the need to obtain help with -h or -help.

Anyway, on to the next one.

 
0
Kudos
 
0
Kudos

Now read this

Python testing (pt 1)

As someone who is a big fan of Behaviour Driven Development (BDD) and Test-Driven Development (TDD) for robust and context specific development, I really need to ensure I am comfortable with a python test framework that I can have in my... Continue →