[Baypiggies] argparse, positional arguments to a single var?

Mark Voorhies mvoorhie at yahoo.com
Tue Jul 31 18:31:42 CEST 2012


On 07/31/2012 08:31 AM, Aleksandr Miroslav wrote:
> Perhaps I am doing this all wrong, or perhaps I have given the wrong
> options to argparse. I hope someone can point out my mistake:
>
> Requirements:
>
>      - given a long list, I have a script that will take in patterns and
>        filter the list and print out the results. This is fairly easily
>        done. So given the list:
>
>            apple
>            apple pie
>            banana
>            carrot
>
>        my script "./filter apple" would print out
>
>            apple
>            apple pie
>
>      - I also want the user to be able to specify inverse patterns, i.e.
>        patterns that should not match, so given same list, and run like
>        this: "./filter apple -v pie", it would print out just apple. This
>        is also doable, and I have no problems getting this working.
>
>      - I want my filter script to take as many patterns and inverse
>        patterns as possible, i.e.
>
>            ./filter pat1 pat2 pat3 -v ipat1 -v ipat2 -v ipat3
>
>        Now here is the tricky part, I want the user to be able to specify
>        patterns and anti patterns on the command line, in any order, thus
>        something like this:
>
>            ./filter pat1 -v ipat1 pat2 -v ipat2 pat3 -v ipat3
>
>        Means we have 3 patterns to grep for: pat1, pat2, and pat3, and 3
>        inverse patterns to grep out: ipat1, ipat2, and ipat3.
>
> I can't get this last bit to work with argeparse. Here's my code:
>
>      import argparse
>      parser = argparse.ArgumentParser()
>      parser.add_argument('-v', action="append", dest='antipattern',
> help="inverted match")
>      parser.add_argument('pattern', action='append', nargs='*',
> help="grep patterns")
>      print parser.parse_args()
>
> With the above code, this works as expected:
>
>      ./filter.py pat1 pat2 pat3  -v ipat1 -v ipat2 -v ipat3
>      Namespace(antipattern=['ipat1', 'ipat2', 'ipat3'],
> pattern=[['pat1', 'pat2', 'pat3']])
>
> But this doesn't:
>
>      ./filter.py pat1 -v ipat1 pat2 -v ipat2  pat3  -v ipat3
>      usage: filter.py [-h] [-v ANTIPATTERN] [pattern [pattern ...]]
>      filter.py: error: unrecognized arguments: pat2 pat3
>
> I want all the positional arguments to go into a single argument.
>
> Is this doable?

Use parse_known_args:

import argparse
p = argparse.ArgumentParser()
p.add_argument("-v", action = "append")
p.parse_known_args("d e -v 1 -v 2 i j -v 3 a b c".split())

# (Namespace(v=['1', '2', '3']), ['d', 'e', 'i', 'j', 'a', 'b', 'c'])

(alternatively, you could copy egrep's interface...)

HTH,

Mark


More information about the Baypiggies mailing list