3

I have a program that produces an array of data and prints it out very nicely. The challenge for which I seek a solution is as follows:

  • Muck up the data in the array before it gets printed, e.g., sticking in non-UTF-8 characters, putting the fields in the wrong order, changing the date format.
  • Let the user pick which "muck ups" occur.

Here is a stripped-down version of my existing program that works, whose output I wish to intercept and muck up:

ex_matrix = [[402, 'Mayonnaise', '0123', 2014-12-18, '(Burlington, -, -)', 1.0],
             [413, 'Peanuts', '0177', 2014-11-10, '(Place, Florida, South Afrika)', 1.0],
             [415, 'Seaweed', '0713', 2014-12-02, '(The Pub, -, Newfoundland)', 1.0]]

def print_forecasts(matrix, num_rows):
    for r in xrange(num_rows):
        print("{%s, [%s, %s, %s, %s], %s}" % (matrix[r][0], matrix[r][1],
              matrix[r][2], matrix[r][3], matrix[r][4], matrix[r][5]))
        print "# Generated using pickles_program.py \n"

def main():
    print_forecasts(ex_matrix, 3)

main()

From what I've read of Python's argparse tutorial, the PEP re. argparse, and several StackOverflow answers, it seems argparse is the key to this problem. Here is what I've written, just trying to get a feel for how argparse works:

import argparse

num_rows = 3

parser = argparse.ArgumentParser(description="base rate model: error adder")

parser.add_argument("muck2", help="muck up the population field", nargs='?')
args = parser.parse_args()
for i in xrange(num_rows):
    matrix[i][1] = "^&*#$)(*DJJJJ)"
    print matrix

There will be >10 types of muck-up's for the user to choose from. What I think I would like would be for the user to be able to say to the command-line, "python pickles_program.py 1 3 8 11," or something like that, and have the muck-up's 1, 3, 8 and 11 happen, and for "python pickles_program.py --help" to display all the muck-up options.

I hope you'll forgive me if this is a dull-witted question. I'm a Python novice and still learning how to use the many resources there are for learning this great language, but I've searched SO and Python documentation high and low -- please believe me, if there is an answer to my problem out there, it's either not been explained well enough for people like me, or it's too darned hard to find, because I haven't found it yet.

Please advise, esp. on how I can pose my question better/more clearly!

2 Answers2

2

It will be MUCH easier in my opinion to handle your "muck ups" as flags, instead of numbers. Then, you can use ArgParse to check if those flags are enabled. For example:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--verbose", help="increase output verbosity",
                    action="store_true")
args = parser.parse_args()
if args.verbose:
   print "verbosity turned on"

This way, add all of your "muck ups" via parser.add_argument("argument", action="store_true") then do the logic for each "muck up" under a series of if statements.

  • If you MUST use numbers, please reply and I'll figure out a solution. – John Martinelli Jul 19 '15 at 17:48
  • No, by all means -- I have no attachment to using numbers! In fact, flags are a concept I meant to ask about. I have seen them talked about a lot, but have not yet got a handle on what they are. Can you explain them, or refer me to someplace that does? – Molly G Hickman Jul 19 '15 at 18:06
  • Flags are arguments, except you can have them in any position. For example: nmap -sS 127.0.0.1 -p0 and nmap -p0 -sS 127.0.0.1 produce the same result. They allow you to "TRUE" or "NULL" a variable if they, or if they do not, exist, as well as assign values to a flag. For example, -p = 0 in the above nmap example. – John Martinelli Jul 21 '15 at 22:47
0

For your learing purposes, it would be good to start without any extra modules. Just work from the sys.argv directly. For example

import sys
muck_ups = []
if sys.argv[1:]:  # values beyond the program name
    muck_ups = [int(i) for i in sys.argv[1:]]
    # this will throw an error if one of the strings can't be converted to an int
    # we can refine that later

if len(muck_ups)==0:
    print('help...')
    sys.exit(1)
    # print help if they don't give you any numbers

for m in muck_ups:
    if m in [1]:
       pass # do one muckup
    elif m in [2]:
       <do another>
    elif m in [3]:
       <etc>
    else:
        print('muckup %s not found'%m)

muck_ups values don't have to be numbers. They could be strings, and you could have aliases, e.g.

 elif m in [1,'1','one','first']:
    ....

Use logic like this if you want to perform the actions in the order indicated by the muck_ups values. You'd want to use a different logic if you want to do action1 if 1 in muck_ups, then action2 if 2 in muck_ups:, etc.

A simple argparse parser with:

parser.add_argument('muck_ups', type=int, nargs='*')

would gave the same list of integers in args.muck_ups. If you want to add more switches and options, argparse would useful, but for just one parameter like this, it doesn't make much difference.

argparse (and related modules) is primarily a way of parsing the input; of figuring out what the user wants to do. It isn't an execution mechanism. And don't get hungup over making it do something fancy.

hpaulj
  • 221,503
  • 14
  • 230
  • 353