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