Heisenberg strikes again!
David C. Fox
davidcfox at post.harvard.edu
Wed Sep 10 17:38:27 EDT 2003
neeson wrote:
> Alright, I'm fairly new to Python, and this one has got me stumped.
> I've just started to write a cli program that'll use readline, and
> I've attached the relevant bits.
>
> Here's the mystery: If I so much as /look/ at the list 'matches',
> readline stops working. Run the program, hit tab at the prompt,
> you'll get 'one', which is incorrect, as there are in fact four
> possible completions. Now comment out the line that I've marked
> (which, incidentally, does nothing). /Now/ it works.
>
> Is there some very strange side effect to accessing a list element
> that I'm unaware of? I've tried it in two different versions of
> Python.
No, but there is a side effect of accessing the first element of an
empty list: namely, Python raises an IndexError exception (i.e. index
out of range).
> Any elightenment would be appreciated...
>
> Heath
>
> import readline
> import sys
>
> commands = ["one", "two", "three", "four"]
> matches = []
>
> def comp(text, state):
> if state == 0:
> matches = []
Because you haven't used
global matches
the next statement creates a new list called matches as a variable local
to comp. All your matching commands are added to this variable, which
disappears when comp returns.
> n = len(text)
> for cmd in commands:
> if cmd[:n] == text:
> matches.append(cmd)
> throwaway = matches[0] # <--- Comment out this line
When comp is called with state == 0, matches is still referring to the
local list which is not empty (unless there were no matches to the
text), so this line does indeed do nothing. However, when comp is
called with state != 0, this line refers to the global matches list,
which is empty, so it raises an IndexError, and the following line is
not reached.
Apparently, readline treats an exception in the completer as equivalent
to returning None. In fact, you seem to be relying on this behavior
implicitly in the line below, because you are not checking whether state
< len(commands)
> return commands[state]
>
> readline.set_completer(comp)
> readline.parse_and_bind("tab: complete")
David
More information about the Python-list
mailing list