IndexError: string index out of range

Steve Holden sholden at holdenweb.com
Wed Apr 11 21:21:57 EDT 2001


"michael" <mhyoung at valdosta.edu> wrote in message
news:mailman.987034096.12363.python-list at python.org...
> #!/usr/bin/python
>
> import sys
>
> FILENAME = "./testfile"
> EXCLUDE='#'   #Lines beginning with this should not be printed.
>
> def get_line() :
>   buf = f.readline()
>   if (buf[0] == EXCLUDE):
>     return 0
>   else:
>     return buf
>
The problem here is that you are testing for the line beginning with a "#"
before you know whether you have encountered the end of the file. That's why
you get an error at EOF.

> f = open(FILENAME, "r")
>
Also note that you set f here, but use it (as a global) int he function.
While this is possible, it's generally better practice (and more flexible)
to pass it in to your function as an argument. I wouldn;t worry too much
about that just now, though.

> while 1:
>   buf = get_line()
>   if (buf == ''):
>     break
Here you correctly test for EOF before testing for a comment line, but it's
too late, the damage was done in get_line()!

>   if (buf == 0):   # If 0 is returned then the line read on this loop
> begins with
>     continue        #    the EXCLUDE char and is not to be printed
>   else:
>     sys.stdout.write(buf)
>
The above logic might be more succinctly expressed as

if buf:            # zero tests false. None might be better?
    sys.stdout.write(buf)

> f.close()
>
> #############   END OF PROGRAM   ##############
>
> Im new to Python.This is my prgram. It reads the contents of testfile
> line by line and prints it out unless the line begins with a #. I know
> that it might be pointless to use a function for this but it is for
> learning purposes. This program works fine until it gets to the last
> line in the testfile and I get this error.
>
> Traceback (innermost last):
>   File "./test3.py", line 18, in ?
>     buf = get_line()
>   File "./test3.py", line 10, in get_line
>     if (buf[0] == EXCLUDE):
> IndexError: string index out of range
>
> Can someone please tell me what I'm doing wrong? I've looked all over
> the net and in several books for a solution.
>
You didn't go too far wrong, just a simple sequencing error. In this case,
would it actually be better to have the read routine keep going until it
either hits EOF or finds a line which needs processing? The following code
is untested, just to give you the idea...

def get_line():        # return a non-comment line or EOF
    l = f.readline()
    if not f:            # empty strings also test false
        return f
    if f[0] == "#":
        return get_line()

This recursive solution removes the comments before they have time to get
troublesome. If you don;t like recursion (a function calling itself) then
you could equivalently write:

def get_line():    # return a non-comment line or EOF
    while 1:
        l = f.readline()
        if not f:
            return f
        if f[0] != "#":
            return l

This simplifies your main program, because now it never sees the comment
lines and so only needs to worry about end of file.

Does this help?

regards
 Steve







More information about the Python-list mailing list