[Tutor] raise exception works as planned in program but not when imported into testing module

Jim Mooney Py3.4.3winXP cybervigilante at gmail.com
Thu Apr 30 03:05:29 CEST 2015


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


More information about the Tutor mailing list