argparse limitations

Oscar Benjamin oscar.j.benjamin at gmail.com
Tue Jul 31 13:45:51 CEST 2012


On 31 July 2012 12:03, Benoist Laurent <benoist at ibpc.fr> wrote:

> Finally.
>
> The code I proposed doesn't work in this case: if you add any positional
> argument to one of the subparsers, then the parsing doesn't work anymore.
> The reason seems to be that argparse thinks the last argument of the first
> parser is the last but one argument.
> Hence, if a subparser takes some arguments, it fails.
>
> Example: if the "-n" argument of the foo parser is set mandatory (so
> becomes "n" instead of "-n")
>
> python toto.py foo.txt bar.txt foo 10
> usage: toto.py [-h] [fname [fname ...]] command ...
> toto.py: error: argument command: invalid choice: '10' (choose from 'foo',
> 'bar')
>

What about:

$ python toto.py foo.txt bar.txt foo -n 10

Note that contrary to what you said above, your program does not work like
a "standard unix tool". A standard command line program to do what you want
would normally look like

$ python toto.py foo -n 10 foo.txt bar.txt

or perhaps

$ python toto.py foo foo.txt bar.txt -n 10

so that the algorithm for differentiating the command 'foo' from the
filenames is well defined. How do you propose that your user enters a
filename 'foo'?

Oscar.


>
> Any solution?
>
> Cheers,
> Ben
>
>
>
> Le Jul 31, 2012 à 12:37 PM, Benoist Laurent a écrit :
>
> Really sorry about that.
>
> So, for the community, below is the full code for a tool that behaves like
> a Unix standard tool.
> It takes in argument the files to process and a command.
>
> """Just to setup a command-line parser that acts just like a unix
> standard tool."""
>
> import argparse
> import sys
>
> def define_options():
>     parser = argparse.ArgumentParser()
>     parser.add_argument("fname", help="input file", nargs="*")
>
>     # create subparsers
>     subparsers = parser.add_subparsers(dest="cmd", metavar="command")
>
>     # create the parser for the "foo" command
>     get_parser = subparsers.add_parser("foo", help="foo help")
>     get_parser.add_argument("-n", help="number of foo to print",
>                             type=int, default=10)
>
>     # create the parser for the "bar" command
>     sum_parser = subparsers.add_parser("bar", help="bar help")
>
>     return parser
>
>
> if __name__ == '__main__':
>     args = define_options().parse_args()
>
>     if not args.fname:
>         content = sys.stdin.read()
>         # do something
>     else:
>         for fname in args.fname:
>             with(open(fname, "rt")) as f:
>                 content = f.read()
>             # do somet
>
>
> Benoist
>
>
>
> Le Jul 31, 2012 à 11:55 AM, Oscar Benjamin a écrit :
>
>
> On Jul 31, 2012 10:32 AM, "Benoist Laurent" <benoist at ibpc.fr> wrote:
> >
> > Well sorry about that but it seems I was wrong.
> > It was Friday evening and I guess I've not been careful.
> >
> > Actually when you specify nargs="?",  the doc says "One argument will be
> consumed from the command line if possible, and produced as a single item".
> > So you can't pass several arguments to the program.
>
> Right below that in the docs it explains about using nargs='*' and
> nargs='+'. One of those will do what you want.
>
> Oscar.
>
> >
> > So, to rephrase the question, how can I get a argument parser that
> parses the command-line just as Unix grep would do?
> > i.e.
> >
> > $ echo 42 > foo.txt
> > $ echo 172 >> foo.txt
> > $ cp foo.txt bar.txt
> > $
> > $ grep 42 foo.txt
> > 42
> > $ grep 42 foo.txt bar.txt
> > foo.txt:42
> > bar.txt:42
> > $ cat foo.txt | grep 42
> > 42
> > $ grep -c 42 foo.txt
> > 1
> >
> >
> > Cheers,
> > Ben
> >
> >
> >
> >
> > Le Jul 27, 2012 à 7:08 PM, Benoist Laurent a écrit :
> >
> >>
> >>
> >> Yes basically looks like you get it.
> >> I have to further test it but my first impression is that it's correct.
> >>
> >> So actually the point was to use nargs="?".
> >>
> >> Thank you very much.
> >> Ben
> >>
> >>
> >>
> >> Le Jul 27, 2012 à 5:44 PM, Peter Otten a écrit :
> >>
> >>> Benoist Laurent wrote:
> >>>
> >>>> I'm impletting a tool in Python.
> >>>>
> >>>> I'd like this tool to behave like a standard unix tool, as grep for
> >>>>
> >>>> exemple. I chose to use the argparse module to parse the command line
> and
> >>>>
> >>>> I think I'm getting into several limitations of this module.
> >>>>
> >>>>
> >>>>> First Question.
> >>>>
> >>>> How can I configure the the ArgumentParser to allow the user to give
> >>>>
> >>>> either an input file or to pipe the output from another program?
> >>>>
> >>>>
> >>>> $ mytool.py file.txt
> >>>>
> >>>> $ cat file.txt | mytool.py
> >>>
> >>>
> >>> $ echo alpha > in.txt
> >>> $ cat in.txt | ./mytool.py
> >>> ALPHA
> >>> $ cat in.txt | ./mytool.py - out.txt
> >>> $ cat out.txt
> >>> ALPHA
> >>> $ ./mytool.py in.txt
> >>> ALPHA
> >>> $ ./mytool.py in.txt out2.txt
> >>> $ cat out2.txt
> >>> ALPHA
> >>> $ cat ./mytool.py
> >>> #!/usr/bin/env python
> >>> assert __name__ == "__main__"
> >>>
> >>> import argparse
> >>> import sys
> >>>
> >>> parser = argparse.ArgumentParser()
> >>> parser.add_argument("infile", nargs="?", type=argparse.FileType("r"),
> >>> default=sys.stdin)
> >>> parser.add_argument("outfile", nargs="?", type=argparse.FileType("w"),
> >>> default=sys.stdout)
> >>> args = parser.parse_args()
> >>>
> >>> args.outfile.writelines(line.upper() for line in args.infile)
> >>>
> >>> Is that good enough?
> >>>
> >>>
> >>> --
> >>> http://mail.python.org/mailman/listinfo/python-list
> >>>
> >>
> >> --
> >> Benoist Laurent
> >> Laboratoire de Biochimie Theorique / CNRS UPR 9080
> >> Institut de Biologie Physico-Chimique
> >> 13, rue Pierre et Marie Curie
> >> F-75005 Paris
> >> Tel. +33 [0]1 58 41 51 67 or +33 [0]6 21 64 50 56
> >>
> >> --
> >> http://mail.python.org/mailman/listinfo/python-list
> >
> >
> > --
> > Benoist Laurent
> > Laboratoire de Biochimie Theorique / CNRS UPR 9080
> > Institut de Biologie Physico-Chimique
> > 13, rue Pierre et Marie Curie
> > F-75005 Paris
> > Tel. +33 [0]1 58 41 51 67 or +33 [0]6 21 64 50 56
> >
> >
> > --
> > http://mail.python.org/mailman/listinfo/python-list
> >
>
>
> --
> Benoist Laurent
> Laboratoire de Biochimie Theorique / CNRS UPR 9080
> Institut de Biologie Physico-Chimique
> 13, rue Pierre et Marie Curie
> F-75005 Paris
> Tel. +33 [0]1 58 41 51 67 or +33 [0]6 21 64 50 56
>
> --
> http://mail.python.org/mailman/listinfo/python-list
>
>
> --
> Benoist Laurent
> Laboratoire de Biochimie Theorique / CNRS UPR 9080
> Institut de Biologie Physico-Chimique
> 13, rue Pierre et Marie Curie
> F-75005 Paris
> Tel. +33 [0]1 58 41 51 67 or +33 [0]6 21 64 50 56
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20120731/cae57759/attachment.html>


More information about the Python-list mailing list