Question

def menurender():
global pos
global menulist
line1=menulist[pos]
if pos == len(menulist):
    line2="back"
else:   
    line2=menulist[pos+1]

lcd.clear()
lcd.message(str(pos)+' ' +line1+ "\n"+str(pos+1)+' '+ line2)

In my block of code, I have a conditional in the menurender() function that checks to make sure that the list menulist has a valid index before referencing it, but i receive IndexError: list index out of range. I understand that the else statement is causing it, but I am confused because python shouldn't be executing it.

Full code

    #!/usr/bin/python

#################################################
#IMPORTS#########################################
#################################################
from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate
from Adafruit_I2C import Adafruit_I2C

#################################################
#OBJECTS#########################################
#################################################
lcd = Adafruit_CharLCDPlate()


#################################################
#VARIABLES#######################################
#################################################
#current button value
prevbutton = "NULL"
#for SELECT key and determining clicks
action = False
#variable for menu position
pos = 0
#on screen cursor 0 for top line, 1 for bottom line
cursor = 0

#Handles list structure and action when clicked
menulist= []
menulist.append("CPU")
menulist.append("RAM")
menulist.append("STORAGE")
menulist.append("NETWORK")


#get input from keys and return the currently pressed key
def buttonstatus():
    bstatus = "Null"
    if lcd.buttonPressed(lcd.SELECT) == True:
        bstatus="SELECT"
    elif lcd.buttonPressed(lcd.UP) == True:
        bstatus="UP"
    elif lcd.buttonPressed(lcd.DOWN) == True:
        bstatus="DOWN"
    elif lcd.buttonPressed(lcd.LEFT) == True:
        bstatus="LEFT"
    elif lcd.buttonPressed(lcd.RIGHT) == True:
        bstatus="RIGHT"
    return bstatus

#checks buttons pressed and converts that into action for top menu

def getinput():
    global prevbutton
    global pos
    if buttonstatus() != prevbutton:
        prevbutton = buttonstatus()
        if buttonstatus() == "SELECT":
            print "select"
        elif buttonstatus() == "DOWN":
            pos = pos + 1
        elif buttonstatus() == "UP":
            pos = pos -1
        #elif buttonstatus() == "LEFT":
            #print "left"
        #elif buttonstatus() == "RIGHT":
            #print "right"

#defines bounds for the position of the cursor
def posbounds():
    global pos
    global menulist
    if pos < 0:
        pos = 0
    if pos == len(menulist):
        pos = len(menulist)


#code renders the menu on the LCD
def menurender():
    global pos
    global menulist
    line1=menulist[pos]
    if pos == len(menulist):
        line2="back"
    else:   
        line2=menulist[pos+1]

    lcd.clear()
    lcd.message(str(pos)+' ' +line1+ "\n"+str(pos+1)+' '+ line2)


while True:
    getinput()
    posbounds()
    menurender()
Was it helpful?

Solution

There are lots if values for pos != len(menulist) for which menulist[pos+1] gives an IndexError (including pos == len(menulist) - 1). You should check

if pos > (len(menulist) - 2):

OTHER TIPS

You should probably change if pos == len(menulist): to if pos == len(menulist) - 1: if you want to check if pos is the index of the last element, or to if pos == len(menulist) - 2: if you want to check for the second to last element.

A better way of doing this may be by using a try ... except block.

try:
    line2 = menulist[pos+1]
except IndexError:
    # Out of range -> pos is greater than len(menulist)-1
    line2 = 'back'

However - this doesn't seem lika a Pythonic way of doing anything at all in Python. Maybe you could tell us what you are trying to achieve, and someone here may propose a better way of doing it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top