Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python

Python (improved) Math Quiz App (with datetime), formatting within a try: except block with ValueError

After finished the Math Quiz App (within the Kenneth Love Dates and Times with Python) I decided to try to write some improvements. I got it so the program takes a user defined number of questions:

# user defined # of questions?
# user defined range for questions?
# time to asnwer each question?

import datetime
import random

from questions import Add, Multiply

# user input for number of questions
while True:
        try:
            num_of_questions = int(input("How many questions would you like? (Integers only) > "))
            break 
        except ValueError:
            print("Hey smart guy, that ain't no integer I ever heard of!")   

class Quiz:
    questions = []
    answers = []

    def __init__(self):
        question_types = (Add, Multiply)
        # generate 10 random questions range(1,10)
        for _ in range(num_of_questions):
            num1 = random.randint(1, 10)
            num2 = random.randint(1, 10)
            question = random.choice(question_types)(num1, num2)
            self.questions.append(question)
        # add these questions into self.questions


    def take_quiz(self):
        # log start time
        self.start_time = datetime.datetime.now()

        # ask questions
        for question in self.questions:
            # log if questions asnwered correctly
            self.answers.append(self.ask(question))
        else:
            # log the end time
            self.end_time = datetime.datetime.now()


        # show a summary
        return self.summary()

    def ask(self, question):
        correct = False
    # log start time
        question_start = datetime.datetime.now()

    # capture answer
        answer = input(question.text + ' ? ')
    # check answer
        if answer == str(question.answer):
            correct = True
    # log end time
        question_end = datetime.datetime.now()
    # if the answer correct, return true, 
    # otherwise send back false
    # return elapsed time
        return correct, question_end - question_start

    def total_correct(self):
        # return the total # of correct answers
        total = 0
        for answer in self.answers:
            if answer[0]:
                total += 1
        return total
    def summary(self):
        print("You got {} out of {} correct!".format(
                self.total_correct(), len(self.questions)
        ))

        if self.total_correct() == len(self.questions):
            print("You must be some kind of genius, you got 'em all right!")

        elif self.total_correct() == 0:
            print("You are a total retard! You answered zero questions correctly!") 

        print("It took you {} seconds total!".format(
                (self.end_time-self.start_time).seconds
        ))

Quiz().take_quiz()

So far so good. I tried to to make it so the program could take the input that caused the ValueError (e.g. they typed a letter instead of an integer) and have the program return a formatted string with the offending letter, like so:

while True:
        try:
            num_of_questions = int(input("How many questions would you like? (Integers only) > "))
            break 
        except ValueError:
            print("Hey smart guy, {} ain't no integer I ever heard of!".format(num_of_questions))  

When run with the above lines added the shell spits out:

"num_of_questions not defined"

So I then tried :

while True:
        try:
            num_of_questions = int(input("How many questions would you like? (Integers only) > "))
            break 
        except ValueError:
            print("Hey smart guy, {} ain't no integer I ever heard of!".format(ValueError))  

Thinking that maybe the input was captured as the ValueError and it could be used like a variable in the format . Alas the shell yields:

How many questions would you like? (Integers only) > a Hey smart guy, <class 'ValueError'> ain't no integer I ever heard of!

I am trying to get it so that it types out: "Hey smart guy, [user input that causes ValueError] ain't no integer I ever heard of"

Do I have to create a str for the ValueError to make it print? I am not sure how to proceed

2 Answers

Hi, Robert- it is erroring out on the "int", so "num_of_questions" never captures the user input. So if you could pull the "int" out of there and put it in a separate line, I think it will work:

while True:
    try:
        num_of_questions = input("How many questions would you like? (Integers only) > ")
        num_of_questions = int(num_of_questions)
        break
    except ValueError:
        print("Hey smart guy, '{}' ain't no integer I ever heard of!".format(num_of_questions))

In addition, I think you'd find the "Raising Exceptions" part of Byte of Python helpful if you'd like to know more: https://python.swaroopch.com/exceptions.html

As Sean Connery said to the kid in "Finding Forester",

"You're the man now, Dog!"

Thanks for your help

Hahaha, Thanks!