Hey guys,
I've been lurking around these forums for a few weeks now, and this website is by far the most helpful of any site I've visited as far as honing my newfound Python skills, and I figured it's time I jump in and ask some of the more specific questions that have been plaguing me. So here goes.

I'm working on my first non-school-assigned program, just a simple unit converter, and I'm having some trouble with the raw_input() method. If I code it like the following code block, everything works fine:

def distanceConverter(dfrom, funit, dto, tunit):
    print dfrom
    print dto
    print funit
    print tunit


def distance():
    msg="1) Millimeters \n"
    msg+="2) Centimeters \n"
    print msg
#prints list of from options
    choice=input("Select unit to convert from:")

    if choice==1:
        dfrom=1
        funit="millimeters"
    elif choice==2:
        dfrom=2
        funit="centimeters"
    else:
        print "Invalid entry. Please select 1 or 2"

    print msg
    choice=input("Select unit to convert to:")

    if choice==1:
        dto=1
        tunit="millimeters"
    elif choice==2:
        dto=2
        tunit="centimeters"
    else:
        print "Invalid entry. Please select 1 or 2"


    distanceConverter(dfrom,funit,dto,tunit)

def mass():
    print "mass function tester"
def velocity():
    print "velocity function tester"


def main():
    msg="Welcome to Rob's Unit Converter Build 1.0."
    print msg
#prints the opening message and list of unit options
    msg="1) Distance \n"
    msg+="2) Mass/Weight \n"
    msg+="3) Velocity"
    print msg
    choice=4
    while choice>3:
        choice=input("Please select the unit type:")
        if choice==1:
            distance()
        elif choice==2:
            mass()
        elif choice==3:
            velocity()
        else:
            print "Invalid selection, please enter 1, 2, or 3."
if __name__=='__main__':
    main()

The problem is in the distance() function. If I use input() like I did above, and prompt for an integer value, everything goes smoothly. But, if I use raw_input(), and prompt for a string, like the following, (so the user can type 'millimeters' or 'centimeters' instead of just 1 or 2), I get this error: "UnboundLocalError: local variable 'dfrom' referenced before assignment."

def distanceConverter(dfrom, funit, dto, tunit):
    print dfrom
    print dto
    print funit
    print tunit


def distance():
    msg="1) Millimeters \n"
    msg+="2) Centimeters \n"
    print msg
#prints list of from options
    choice=raw_input("Select unit to convert from:")

    if choice==('1','millimeters','Millimeters'):
        dfrom=1
        funit="millimeters"
    elif choice==('2','centimeters','Centimeters'):
        dfrom=2
        funit="centimeters"
    else:
        print "Invalid entry. Please select 1 or 2"

    print msg
    choice=raw_input("Select unit to convert to:")

    if choice==('1','millimeters','Millimeters'):
        dto=1
        tunit="millimeters"
    elif choice==('2','centimeters','Centimeters'):
        dto=2
        tunit="centimeters"
    else:
        print "Invalid entry. Please select 1 or 2"


    distanceConverter(dfrom,funit,dto,tunit)

def mass():
    print "mass function tester"
def velocity():
    print "velocity function tester"


def main():
    msg="Welcome to Rob's Unit Converter Build 1.0."
    print msg
#prints the opening message and list of unit options
    msg="1) Distance \n"
    msg+="2) Mass/Weight \n"
    msg+="3) Velocity"
    print msg
    choice=4
    while choice>3:
        choice=input("Please select the unit type:")
        if choice==1:
            distance()
        elif choice==2:
            mass()
        elif choice==3:
            velocity()
        else:
            print "Invalid selection, please enter 1, 2, or 3."
if __name__=='__main__':
    main()

Does anyone have any ideas as to what's causing the error?

NOTE: I am very new to programming, and I'm sure that this program can be written MUCH more efficiently, but this is by far the most complex program I've written to date, so I'm just trying to get it working before I mess with making it more efficient or implementing a GUI. However, if anyone has any tips for making the program more efficient, I'm all ears. Or eyes. You get it.

Also, I realize that this is a lot of code, but I've slimmed it down a lot already lol.
Also note that you need to input 1 at the first prompt to access the distance() function in question, but I'm sure you already knew that.
This is being written for Python 2.7.1, if that matters at all.


Any and all help is much appreciated.

You are using Python 2.x which has two functions:

You (almost) never want to use input() when interacting with users: Too fraught with difficulty. Instead, use raw_input() and if you need some other type than string, then for example:

while True:
    try:
        value = int(raw_input(the_prompt)) # assuming you need an int
        break # User gave us an integer as required: leave the loop
    except:
        # (L)user gave us a non-integer. Try again
        # Assume one reminder is sufficient, otherwise do something smarter
        the_prompt = "Need an integer: %s"%the_prompt

Edited 5 Years Ago by griswolf: n/a

rscubelek

strip() can save a lot when taking user inputs.
Try and split() your user inputs and you have saved yourself 80% of worries. check this out.

foo=" hello" #1
foo="hello"  #2

The 2 foos variables are not the sane from user inputs with the check of equality sign ==.

They are only the same after strip() is called.
:)

I know the difference between the two functions, but I'm still having the problem with using raw_input() instead of input(). The idea is that instead of being forced to enter the numerical code for the unit, the user would also be able to input strings like "millimeters" or "feet".

And richieking, how would I use the strip() or split() functions to fix the problem? I'm a complete newbie, so an example of an implementation of the code would be very helpful.

Thanks for the replies guys.

The cause of your problem is in the error message if you look closely. You should (and can) read and parse the error messages carefully: The compiler/interpreter authors are trying to be helpful here, so the information you need is probably there (though often written so generically that it is hard to understand): UnboundLocalError: local variable 'dfrom' referenced before assignment Unfortunately, you didn't paste the full error message which would have also told you which line the problem is on. Should I guess line 37? Prove this by, near line 9, giving dfrom and the other variables default (and obviously bogus) values to see what happens.

P.S. You can simplify your code to handle user-input strings like this:

ans = raw_input(prompt).strip().lower()
if ans.startswith('mm') or ans.startswith('mill'): # mm, millimeter, Millimeter.
  # handle mm
elif ans.startswith('in'):
  # handle inch
# and so forth

Edited 5 Years Ago by griswolf: n/a

Here is your full working code.

I just changed few thing.

def distanceConverter(dfrom, funit, dto, tunit):
    print dfrom
    print dto
    print funit
    print tunit


def distance():
    msg="1) Millimeters \n"
    msg+="2) Centimeters \n"
    print msg
#prints list of from options
    choice=raw_input("Select unit to convert from:")

    if choice in ('1','millimeters','Millimeters'):
        dfrom=1
        funit="millimeters"
    elif choice in ('2','centimeters','Centimeters'):
        dfrom=2
        funit="centimeters"
    else:
        print "Invalid entry. Please select 1 or 2"

    print msg
    choice=raw_input("Select unit to convert to:")

    if choice in ('1','millimeters','Millimeters'):
        dto=1
        tunit="millimeters"
    elif choice in('2','centimeters','Centimeters'):
        dto=2
        tunit="centimeters"
    else:
        print "Invalid entry. Please select 1 or 2"


    distanceConverter(dfrom,funit,dto,tunit)

def mass():
    print "mass function tester"
def velocity():
    print "velocity function tester"


def main():
    msg="Welcome to Rob's Unit Converter Build 1.0."
    print msg
#prints the opening message and list of unit options
    msg="1) Distance \n"
    msg+="2) Mass/Weight \n"
    msg+="3) Velocity"
    print msg
    choice=4
    while choice>3:
        choice=input("Please select the unit type:")
        if choice==1:
            distance()
        elif choice==2:
            mass()
        elif choice==3:
            velocity()
        else:
            print "Invalid selection, please enter 1, 2, or 3."
if __name__=='__main__':
    main()

Happy codding :)

Aha! Thats it, I was using

if choice==('1','millimeter')

instead of

if choice in ('1','millimeter')

Thank you so much guys. Also, I've implemented the lower() method, which helps a lot with functionality.

Thank you guys!

This question has already been answered. Start a new discussion instead.