Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #111041 > unrolled thread
| Started by | Chris Angelico <rosuav@gmail.com> |
|---|---|
| First post | 2016-07-04 21:36 +1000 |
| Last post | 2016-07-26 11:12 +1000 |
| Articles | 9 — 4 participants |
Back to article view | Back to comp.lang.python
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: Spot the bug: getoptquestion.py Chris Angelico <rosuav@gmail.com> - 2016-07-04 21:36 +1000
Re: Spot the bug: getoptquestion.py jornws0718@xs4all.nl (Oscar) - 2016-07-04 12:38 +0000
Re: Spot the bug: getoptquestion.py Chris Angelico <rosuav@gmail.com> - 2016-07-04 23:42 +1000
Re: Spot the bug: getoptquestion.py Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-07-05 21:04 -0700
Re: Spot the bug: getoptquestion.py Chris Angelico <rosuav@gmail.com> - 2016-07-06 14:14 +1000
Re: Spot the bug: getoptquestion.py jornws0718@xs4all.nl (Oscar) - 2016-07-07 11:30 +0000
Re: Spot the bug: getoptquestion.py Chris Angelico <rosuav@gmail.com> - 2016-07-07 22:12 +1000
Re: Spot the bug: getoptquestion.py jornws0718@xs4all.nl (Oscar) - 2016-07-07 12:29 +0000
Re: Spot the bug: getoptquestion.py Steven D'Aprano <steve@pearwood.info> - 2016-07-26 11:12 +1000
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2016-07-04 21:36 +1000 |
| Subject | Re: Spot the bug: getoptquestion.py |
| Message-ID | <mailman.66.1467632176.2295.python-list@python.org> |
On Mon, Jul 4, 2016 at 9:24 PM, Oscar <jornws0718@xs4all.nl> wrote:
> Is this:
>
> a) a bug in getopt.getopt
> b) a bug in my code
> c) a great way to keep me busy for a while
> d) all of the above?
>
>
> #!/usr/bin/python
>
> from __future__ import print_function
> from getopt import getopt, GetoptError
> import sys
>
> try:
> opts, args = getopt(sys.argv[1:], 'b', ['bug '])
>
> except GetoptError as err:
> print('Caught:', repr(err))
>
> else:
> if opts:
> for opt, arg in opts:
>
> if opt in ('-b', '--bug'):
> print ("Ceci n'est pas un bug!")
> else:
> #print ('Missed option: "{0}"'.format(opt))
> print ('Missed option:', opt)
> else:
> print('Usage:', sys.argv[0],'-b|--bug')
Well, first thing I'd do is wipe out your try/except. It's not really
achieving much (you effectively catch an exception to print it to the
console and terminate).
But then what I'm seeing is that you have 'bug ' (with a trailing
space) in your list of long options, so getopt returns '--bug ' as a
long option. Is that a bug? I dunno. Why do you have the trailing
space? In any case, it's pretty easy to see if you change one line of
your code to:
print('Missed option: %r' % opt)
ChrisA
[toc] | [next] | [standalone]
| From | jornws0718@xs4all.nl (Oscar) |
|---|---|
| Date | 2016-07-04 12:38 +0000 |
| Message-ID | <577a58b9$0$5902$e4fe514c@news.xs4all.nl> |
| In reply to | #111041 |
In article <mailman.66.1467632176.2295.python-list@python.org>,
Chris Angelico <rosuav@gmail.com> wrote:
>On Mon, Jul 4, 2016 at 9:24 PM, Oscar <jornws0718@xs4all.nl> wrote:
>> Is this:
>>
>> a) a bug in getopt.getopt
>> b) a bug in my code
>> c) a great way to keep me busy for a while
>> d) all of the above?
>>
>>
>> #!/usr/bin/python
>>
>> from __future__ import print_function
>> from getopt import getopt, GetoptError
>> import sys
>>
>> try:
>> opts, args = getopt(sys.argv[1:], 'b', ['bug '])
>>
>> except GetoptError as err:
>> print('Caught:', repr(err))
>>
>> else:
>> if opts:
>> for opt, arg in opts:
>>
>> if opt in ('-b', '--bug'):
>> print ("Ceci n'est pas un bug!")
>> else:
>> #print ('Missed option: "{0}"'.format(opt))
>> print ('Missed option:', opt)
>> else:
>> print('Usage:', sys.argv[0],'-b|--bug')
>
>Well, first thing I'd do is wipe out your try/except. It's not really
>achieving much (you effectively catch an exception to print it to the
>console and terminate).
It does something: it shows that --bug on my commandline did not throw
an GetoptError. I could post the whole 400 line script, but decided to
cut it down to a demonstration of a subtle bug that i introduced in my
script. So far, answers b) and c) certainly do apply.
>But then what I'm seeing is that you have 'bug ' (with a trailing
>space) in your list of long options, so getopt returns '--bug ' as a
>long option.
You found it much faster than I did! ;-)
As i learned now, --b and --bu will also match '--bug ', as they are not
ambigous. So, of course '--bug' also returns '--bug ' in opts.
But it took me quite a while before I found my logic wasn't working
further down the script, just because I somehow introduced a space
character somewhere where it shouldn't have been.
> Is that a bug? I dunno. Why do you have the trailing
>space?
Because I'm stupid. It should not have been there at all. I've been
readjusting and reformatting my long 'getopt' line all day long and
somewhere my thumb must have hit my spacebar when I wasn't paying
attention. So a hard-to-find bug (for me at least) was introduced.
Now I also did not spot the trailing space in the loop where I was
evaluating the options when I added some debug statements. This sure
got me scratching my head. The option is there, why doesn't my code do
what it's supposed to do? I sure was looking in the wrong place. I
better use repr() for debugging purposes next time. Thanks for the tip.
But is this not at least a bit unexpected behaviour from getopt? On one
hand, if I want to have trailing spaces in my longoptions, why not just
play along and allow them? On the other hand, a space is a delimiter on
the commandline. Does it make sense to allow it as a parameter to
getopt()? And if getopt would silently strip it, would that be a bug?
I agree that it's hard to debate wheter it is a bug, but I wanted to
share this experience anyway... ;-)
> In any case, it's pretty easy to see if you change one line of
>your code to:
>print('Missed option: %r' % opt)
Or uncomment my hint in the OP. But repr() is even better indeed.
--
[J|O|R] <- .signature.gz
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2016-07-04 23:42 +1000 |
| Message-ID | <mailman.68.1467639747.2295.python-list@python.org> |
| In reply to | #111047 |
On Mon, Jul 4, 2016 at 10:38 PM, Oscar <jornws0718@xs4all.nl> wrote: > But is this not at least a bit unexpected behaviour from getopt? On one > hand, if I want to have trailing spaces in my longoptions, why not just > play along and allow them? On the other hand, a space is a delimiter on > the commandline. Does it make sense to allow it as a parameter to > getopt()? And if getopt would silently strip it, would that be a bug? > This is really the crux of the matter. Honestly, I've no idea. The getopt module is designed to match the C getopt function, which I've never used; for my command-line parsing, I use argparse instead (usually via some wrapper that cuts down the duplication, like clize). ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Lawrence D’Oliveiro <lawrencedo99@gmail.com> |
|---|---|
| Date | 2016-07-05 21:04 -0700 |
| Message-ID | <a588eed6-bfac-4cc9-be4a-f6ce188247b0@googlegroups.com> |
| In reply to | #111073 |
On Tuesday, July 5, 2016 at 1:42:42 AM UTC+12, Chris Angelico wrote: > The getopt module is designed to match the C getopt function, which I've > never used; for my command-line parsing, I use argparse instead > (usually via some wrapper that cuts down the duplication, like clize). getopt seems so much simpler.
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2016-07-06 14:14 +1000 |
| Message-ID | <mailman.118.1467778498.2295.python-list@python.org> |
| In reply to | #111167 |
On Wed, Jul 6, 2016 at 2:04 PM, Lawrence D’Oliveiro <lawrencedo99@gmail.com> wrote: > On Tuesday, July 5, 2016 at 1:42:42 AM UTC+12, Chris Angelico wrote: > >> The getopt module is designed to match the C getopt function, which I've >> never used; for my command-line parsing, I use argparse instead >> (usually via some wrapper that cuts down the duplication, like clize). > > getopt seems so much simpler. Look at clize: https://github.com/Rosuav/LetMeKnow/blob/master/letmeknow.py I just put docstrings on my functions, slap "@command" above them, and with minimal boilerplate, I have a fully-working command line interface. It's a wrapper around argparse. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | jornws0718@xs4all.nl (Oscar) |
|---|---|
| Date | 2016-07-07 11:30 +0000 |
| Message-ID | <577e3d66$0$5816$e4fe514c@news.xs4all.nl> |
| In reply to | #111168 |
In article <mailman.118.1467778498.2295.python-list@python.org>, Chris Angelico <rosuav@gmail.com> wrote: >On Wed, Jul 6, 2016 at 2:04 PM, Lawrence D’Oliveiro ><lawrencedo99@gmail.com> wrote: >> On Tuesday, July 5, 2016 at 1:42:42 AM UTC+12, Chris Angelico wrote: >> >>> The getopt module is designed to match the C getopt function, which I've >>> never used; for my command-line parsing, I use argparse instead >>> (usually via some wrapper that cuts down the duplication, like clize). >> >> getopt seems so much simpler. > >Look at clize: Okay: | >>> import clize | Traceback (most recent call last): | File "<stdin>", line 1, in <module> | ImportError: No module named clize Mmm... nope. I'm not going to learn a new tool and introduce an extra dependency just to do something as basic as getopt. But then again, coming from a C background, getopt feels kind of familiar. ;-) Thanks all for the input. I think it all boils down to: "If you don't want a space in your long_option, don't put a space in there". >I just put docstrings on my functions, slap "@command" above them, and >with minimal boilerplate, I have a fully-working command line >interface. It's a wrapper around argparse. Looks neat though! -- [J|O|R] <- .signature.gz
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2016-07-07 22:12 +1000 |
| Message-ID | <mailman.128.1467893565.2295.python-list@python.org> |
| In reply to | #111184 |
On Thu, Jul 7, 2016 at 9:30 PM, Oscar <jornws0718@xs4all.nl> wrote: > Thanks all for the input. I think it all boils down to: "If you don't > want a space in your long_option, don't put a space in there". Yeah, I guess, pretty much! > Mmm... nope. I'm not going to learn a new tool and introduce an extra > dependency just to do something as basic as getopt. But then again, > coming from a C background, getopt feels kind of familiar. ;-) >>I just put docstrings on my functions, slap "@command" above them, and >>with minimal boilerplate, I have a fully-working command line >>interface. It's a wrapper around argparse. > > Looks neat though! Yes, it's a third-party dependency. (Sorry, should have mentioned that.) You're welcome to consider that to be too much risk and/or hassle to be worth improving on getopt, but personally, I *really* like the simplicity of just writing docstrings that still read perfectly well as docstrings, and having them create my argparse configs for me. Different strokes for different horses, or something like that. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | jornws0718@xs4all.nl (Oscar) |
|---|---|
| Date | 2016-07-07 12:29 +0000 |
| Message-ID | <577e4b2b$0$5819$e4fe514c@news.xs4all.nl> |
| In reply to | #111185 |
In article <mailman.128.1467893565.2295.python-list@python.org>, Chris Angelico <rosuav@gmail.com> wrote: >Yes, it's a third-party dependency. (Sorry, should have mentioned >that.) You're welcome to consider that to be too much risk and/or >hassle to be worth improving on getopt, but personally, I *really* >like the simplicity of just writing docstrings that still read >perfectly well as docstrings, and having them create my argparse >configs for me. Different strokes for different horses, or something >like that. Well, parsing the arguments was not really the problem in my case. But after parsing I had to look at valid combinations and show helpfull messages if required information is missing or conflicting options were given. I doubt if an extra abstraction layer would have helped me. It did make my typo a bit hard to catch, though... -- [J|O|R] <- .signature.gz
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve@pearwood.info> |
|---|---|
| Date | 2016-07-26 11:12 +1000 |
| Message-ID | <5796b8ec$0$1603$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #111184 |
On Thu, 7 Jul 2016 09:30 pm, Oscar wrote: > Thanks all for the input. I think it all boils down to: "If you don't > want a space in your long_option, don't put a space in there". No, I don't think so. I think we can do better than that: http://bugs.python.org/issue27619 What decided it for me was that the shell getopt on my system ignores leading and trailing spaces. -- Steven “Cheer up,” they said, “things could be worse.” So I cheered up, and sure enough, things got worse.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web