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:
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:
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``````

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``````

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:
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')``

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