Spot the bug: getoptquestion.py

Oscar jornws0718 at xs4all.nl
Mon Jul 4 08:38:17 EDT 2016


In article <mailman.66.1467632176.2295.python-list at python.org>,
Chris Angelico  <rosuav at gmail.com> wrote:
>On Mon, Jul 4, 2016 at 9:24 PM, Oscar <jornws0718 at 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



More information about the Python-list mailing list