[Tutor] raise exception works as planned in program but not when imported into testing module
Dave Angel
davea at davea.name
Thu Apr 30 06:14:57 CEST 2015
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
More information about the Tutor
mailing list