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.
# 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') -- Jim "What a rotten, failed experiment. I'll start over. Maybe dogs instead of monkeys this time." --God _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor