This code glitches. Please help

Below is the code I need help with it.

import calculate_def_external2
import math

result = “”
again = ‘’
user_name = input("Enter your name: ")
coursename = input("Enter your course name: ")
calculate_def_external2.welcome(user_name)

while again.lower() != ‘q’:
user_operation = input(“enter an operation +, -, , /, %, sprt, farenheit, celsius: ")
while user_operation != “+” and user_operation != “-” and user_operation != "

and user_operation != “/” and user_operation != “%” and user_operation != “sqrt”
and user_operation != “farenheit” and user_operation != “celsius”:
user_operation = input("enter an operation +, -, *, /, % sprt, farenheit, celsius: ")
try:
number1 = float(input("Enter 1st value: "))
if user_operation != “sqrt” and user_operation != “farenheit” and user_operation != “celsius”:
number2 = float(input("Enter 2nd value: "))
result = calculate_def_external2.calculate(user_operation, number1, number2)
print(number1, user_operation, number2, “=”, format(result, ‘.2f’))
elif user_operation == “sqrt” or user_operation == “farenheit” or user_operation == “celsius”:
result = calculate_def_external2.calculate_singular(user_operation, number1)
else:
result = calculate_def_external2.calculate_singular(user_operation, number1)
if user_operation == “farenheit”:
if result == int:
print(number1, “converted to”, user_operation, “is”, format(result, ‘.f’))
else:
print(number1, “converted to”, user_operation, “is”,format(result, ‘.2f’))
else:
if result == int:
print(number1, “converted to”, user_operation, “is”, format(result, ‘.f’))
else:
print(number1, “converted to”, user_operation, “is”,format(result, ‘.2f’))
except ValueError:
print(“value has to be a number”)
except ZeroDivisionError:
print(“cannot divide by Zero.”)
except NameError:
print("Incorrect value. Try again. ")
again = input("Enter q to quit: ")
calculate_def_external2.bye(user_name, coursename)

Please post a transcript of a failing run with the full output including
errors, a description of the input you gave it which was not handled,
and a description of what you intended should happen.

I certainly can’t run it (for one thing, where does
“calculate_def_external2” come from?) And anway would need to know what
input you gave it.

All that said, some remarks about the code as it stands, without running
it:

result = ""

I would e inclined to not set this - effictively you’re rpoviding a
result ahead of time. Just leave this out - that way if you try to use
'result" early, Python will tell you so rather than just proceeding with
the bogus value of “”. In larger programmes that might go a long way
before something is obviously wrong, making the bug harder to find.

again = ''

Similar here, but I would instead make this a Boolean, eg True. This way
it expresses your intent that the loop can run again, a true or false
idea.

user_name = input("Enter your name: ")
coursename = input("Enter your course name: ")
calculate_def_external2.welcome(user_name)

while again.lower() != 'q':

and therefore here I’d write:

while again:

(a) it’s easier to read and (b) it isn’t tied to your input("Enter q to quit: ") function call. That way you can change the implementation (eg
change languages to one where “q” is unsuitable) without changing the
control logic itself.

user_operation = input("enter an operation +, -, *, /, %, sprt, farenheit, celsius: ")
while user_operation != "+" and user_operation != "-" and user_operation != "*" \
        and user_operation != "/" and user_operation != "%" and user_operation != "sqrt"\
        and user_operation != "farenheit" and user_operation != "celsius":
    user_operation = input("enter an operation +, -, *, /, % sprt, farenheit, celsius: ")

Here, on the other hand, I would be inclined to go with the “set
user_operation up front” approach, basicly because Python does not have
a “do…until” version of “while”. So something like:

user_operation = None
while user_operation != "+" and user_operation != "-" and user_operation != "*" \
        and user_operation != "/" and user_operation != "%" and user_operation != "sqrt"\
        and user_operation != "farenheit" and user_operation != "celsius":
    user_operation = input("enter an operation +, -, *, /, % sprt, farenheit, celsius: ")

In this way you’ve picked an initial value which is guarrenteed to fail
the test, ensuring that the input() prompt is made the first time.

You can also write the test more succinctly:

while user_operation not in ("+", "-", "*", "/", "%", "sqrt", "farenheit", "celsius"):

Now the loop body:

The first thing is that you have a single try/except for the whole piece
of code. This means that when an except happens you don’t really know
where it came from. Different operations raise diffferent exceptions for
different reasons. You only want to catch the exceptions you specific
know how to handle correctly. Because of this, you would normally try to
put a try/except around the smallest piece of code you can, eg:

try:
    number1 = float(input("Enter 1st value: "))
except ValueError as e:
    print("invalid value:", e)
    continue

This catches exactly failure of float(), prints the actual exception
(which is important for debugging), and continues the outer loop.

Similarly the ZeroDivisionError should only be associated with the “/”
operation and so forth.

You almost never want to catch NameError at all - it means Python saw a
variable name it did not recognise. This is almost always an error in
your code. By printing just “Incorrect value. Try again.” you (a) are
not fixing or accomodating anything and (b) concealing the name what
caused the error, because you haven’t printed the exception itself.

The core rule of thumb is: catch only exceptions where you have a
meaningful thing to do to accomodate it. The objective is not to catch
all exceptions, it is to function correctly. Catching “anything which
you see happen” does not lead to a correctly operating programme.

Finally:

again = input("Enter q to quit: ")

With the change of “again” to be a Boolean I’d rewrite this to:

again = input("Enter q to quit: ") == "q"

That makes “again” True or False. The whole implementation is right here
instead of putting the test for “q” many lines away. This also makes it
easy to change if you decide to do that.

Cheers,
Cameron Simpson cs@cskk.id.au

Hi Michael, and welcome!

We’re volunteers who are giving back to the community out of love for
the language and thanks for the help we received when we were newbies.
We’re not paid to do this, often our time and energy is extremely
limited, and we’re not mind-readers, so the best way to get our
attention is to either:

  • provide us with a really interesting problem; or

  • make it really easy for us to help you.

(Or preferably both :slight_smile:

In your case, this is how you can help us to help you.

If you got an error, please copy and paste the full text of the
traceback, starting with the line “Traceback…” to the end, and show
us. Don’t make us guess what went wrong.

That is probably the most important step of all. Sometimes, we can tell
you how to fix a problem just from the traceback alone even if we
can’t see or run your code. Tracebacks are (sometimes) just that
awesome.

If there is no error, tell us what you expected to happen, and what
happened instead.

It is criticial that the code you show us is complete with no mystery
functions or classes that we cannot see. Don’t make us guess what
calculate_def_external2 does.

That doesn’t mean you should dump the ENTIRE program in our laps and
expect us to dive into it hunting for clues. (We’re not paid to do
that.) It means to keep the code as small as possible, even if you have
to cut it down to the smallest chunk that is relevant.

That sounds like a lot of work, but you would be amazed how many times
doing just that will let you solve your own problem. And if it doesn’t,
you have increased the chances of getting a good answer from us that
will solve your problem for you!

See more discussion here:

http://www.sscce.org/