On 04/29/2015 09:05 PM, Jim Mooney Py3.4.3winXP wrote:
I raised an exception in the parse_string function in my math parser
program, function_tosser.py, and caught it in the calling routine, and that
worked fine. But when I imported function_tosser.py into a test program,
tester.py, it threw the exception in the parse_string function instead of
handling it in the try block in the calling routine. Why did it work in one
and not the other? The testing program works fine if I return None as I did
before, instead of raising the exception.

It'd be nice if you were explicit about which code you're describing. I can make guesses, but your above paragraph leaves a lot of confusion.

I'm guessing you're talking about the line in parse_string():
        raise ValueError

And I assume you're talking about it being referenced in the other file by the line:
        print(ft.parse_string(monkey_wrench), '\n')

But why are you surprised? There's no try/except protecting the latter line, so the exception will be uncaught, and you'll see it reported in parse_string().

> in the try block in the calling routine.

What routine is that? The line I quoted above is in top-level code, not in a routine. And it doesn't have a try/except there.


# function_tosser.py
"""
Takes the name of a binary math operation and two numbers from input,
repeatedly, and displays the results until done
"""


def add(a, b):
     return a + b


def subtract(a, b):
     return b - a

def minus(a, b):
     return a - b


def multiply(a, b):
     return a * b


def divide(a, b):
     return a / b


operations = {'add': add, '+': add, 'plus': add, 'subtract': subtract,
'subtracted': subtract,
               '-': minus, 'minus': minus, 'multiply': multiply, '*':
multiply, 'multiplied': multiply,
               'times': multiply, 'divide': divide, '/': divide, 'divided':
divide}

def test_number(astring):
     """
     Input: A string that should represent a valid int or float. Output:
     An int or float on success. None on failure.
     """
     for make_type in (int, float):
         try:
             return make_type(astring)
         except ValueError: # Previously returned None, which worked. This
works fine here but when imported into the test program
             pass           # it doesn't wait for the try block in the
calling routine.
     return None


def parse_string(math_string):
     """Input: A math string with a verbal or mathematical operation
     and two valid numbers to operate on. Extra numbers and operations
     are ignored. Output: A tuple containing a function corresponding
     to the operation and the two numbers. Returns None on failure.
     """
     operation = None
     tokens = math_string.split()
     numbers = []
     for token in tokens:
         if token in operations:
             operation = operations[token]
         elif test_number(token) != None:
             numbers.append(test_number(token))
         if len(numbers) > 1:
             break
     if operation is None or len(numbers) < 2:
         raise ValueError
     else:
         return operation, numbers[0], numbers[1]

if __name__ == "__main__":
     instructions = '''Enter two numbers and one of the four basid math
operations,
     either mathematical or verbal. i.e. 3 + 2, 12 divided by 14, 10 minus
4, etc.
     Enter done to quit.
     '''
     try:
         user_input = input(instructions)
         while True:
             if user_input == 'done':
                 break
             try:
                 result = parse_string(user_input)
             except ValueError:
                 print("Not a valid math operation.")
             else:
                 func, num1, num2 = result
                 print(func(num1, num2))
             user_input = input()
     except KeyboardInterrupt:
         print("Program terminated by user")

# tester.py

'''Test function_tosser.py mainlogic against random operators, operands,
and bad input'''
import random
import function_tosser as ft
valid_terms = list(ft.operations.keys())
def eval_test():
     pass

trash = ['1 +', 'blah', '3-4', 'gargle', 'Newt Gingrich',
     ",,,,,", '{+=-33.44 minus12 3 times blarg 1445641654644555455']

for ctr in range(50):
     term = ' ' + random.choice(valid_terms) + ' '
     num1 = str(random.randint(1,1000))
     num2 = str(random.randint(1,1000))
     if term == ' subtract ' or term == ' subtracted ': term = ' subtracted
from '
     if ctr % 10 == 0: # stress testing for a None failure
         monkey_wrench = random.choice(trash)
         print(ft.parse_string(monkey_wrench), '\n')
     else:
         func, num1, num2 = ft.parse_string(num1 + term + num2)
         print(func, num1, term, num2)
         print('result:',func(num1, num2), '\n')




--
DaveA
_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor

Reply via email to