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

My solution to the timed math quiz game.

Kinda proud of myself for figuring this all out on my own. The only hand holding I had was Kenneth Love 's pre-planning with the comments. Still kinda confused on the whole self arguments, and at the very end of my script I couldn't get it to run like we did in Hack N' Slash. What I wrote works but it's not as nice as Game() on the final line of that script. I'm also realizing that no matter how good my notes are, this stuff is falling out of my head. I need to come up with ideas of my own to practice every technique I take notes on so I can actually learn how to implement it and remember it and 'think like a programmer'. Anyways here it is!!

import random
import datetime
import pdb

from questions import Add, Multiply

class Quiz(object):
    questions = []
    answers = []
    correct = 0
    wrong = 0

    def __init__(self):
        self.number_of_qs = input("Please enter the number of questions you would like to solve: ")
        self.number_range = input("Enter the range of numbers you would like to work with: ")
        for self.test_qs in range(int(self.number_of_qs)):
            self.generator = [Add(random.randint(1,int(self.number_range)), random.randint(1,int(self.number_range))), \
                              Multiply(random.randint(1,int(self.number_range)), random.randint(1,int(self.number_range)))]
            self.questions.append(self.generator[random.randint(0, 1)])

    def take_quiz(self):
        self.START_TIME = datetime.datetime.now()
        print(self.START_TIME.strftime('%B %d %Y %I:%M %p'))
        for self.an_index in range(int(self.number_of_qs)):
            self.an_answer = input('{} :'.format(self.questions[self.an_index].text))
            self.answers.append(self.an_answer)
            try:
                if int(self.an_answer) == self.questions[self.an_index].answer:
                    print("Great job, that is correct. Next Question!")
                    self.correct += 1
                else:
                    print("Sorry, that answer is incorrect. Next Question...")
                    self.wrong += 1
            except:
                if str(self.an_answer) == 'quit':
                    exit()
                else:
                    print("Please enter a real answer!")

            self.elapsed_time = datetime.datetime.now() - self.START_TIME
            print("Elapsed Time: {}".format(self.elapsed_time.seconds))


    def summary(self):
        print("You got {}/{} correct!".format(self.correct, self.number_of_qs))
        print("This quiz took you {} seconds!".format(self.elapsed_time.seconds))

#pdb.set_trace()
my_quiz = Quiz()
my_quiz.take_quiz()
my_quiz.summary()
input(" ")

Please look over it and let me know what I could do better, what techniques I could have used that would have made it more pythonic and streamlined, or any other good ideas! I'm brain-storming what my first self-driven practice project is going to be. Thanks everyone. :D

Running the file in python interactive: python -i D:\myscripts\quiz2.py

The quit option doesn't work and returns a few weird exceptions.

However running the file in normal python mode everything works just fine. I was really tripped out for a second there. It was working one minute and not working as expected the next until I realized I had hit my shortcut key for running the script in python -i.

4 Answers

So I just looked at the documentation for sys.exit(), and it's meant to raise the SystemExit error. That's part of how it works.

So, you can either move it outside of the try... except blocks, or handle the SystemExit exception... though I assume you actually want the ability to quit. The docs point out that:

Since exit() ultimately “only” raises an exception, it will only exit the process when called from the main thread, and the exception is not intercepted.

in a real world application i doubt anyone would run the script with python -i and would therefore never encounter that ugly wall of exception text. Thank you for clarifying sys.exit() for me. I'll continue to play with it and see if i can get it to terminate more neatly in interactive mode. Also thanks for the tip on having it evaluate for quit before turning it into an int.

On another note, I wish these forums allowed for marking a thread as a 'discussion' rather than a question needing to be answered. I kind of want this thread to be an ongoing suggestion topic for anyone that wants to drop some knowledge on me.

The issue with quitting might be because you're just using exit instead of sys.exit (need to import sys for this obviously).

See this question on Stack Overflow: The difference between exit() and sys.exit() in Python?

I had tried using sys.exit() originally, but it still throws an exception, however this only occurs when trying to run the script in python interactive mode with python -i D:\MyScripts\quiz2.py.

Running the script as: python D:\MyScripts\quiz2.py it runs just fine and i receive no errors.

This is the error it throws in interactive mode if anyone wants to chew on it for a bit. This is the exception it gives even when importing the sys module and turning all exit calls into sys.exit()

Traceback (most recent call last): File "D:\MyScripts\quiz2.py", line 33, in take_quiz if int(self.an_answer) == self.questions[self.an_index].answer: ValueError: invalid literal for int() with base 10: 'quit'

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "D:\MyScripts\quiz2.py", line 55, in <module> my_quiz.take_quiz() File "D:\MyScripts\quiz2.py", line 41, in take_quiz sys.exit() SystemExit

Oh of course, it's because you're checking for quit after you try and convert it to an integer, and only if there's an exception in the first part.

Check for quit first. You don't need to explicitly convert self.an_answer to a string either, because that's the default type coming from the input function.

The quit check can go in the try if you still want to handle exceptions.

Okay so my take_quiz function definition now looks like

    def take_quiz(self):
        self.START_TIME = datetime.datetime.now()
        print(self.START_TIME.strftime('%B %d %Y %I:%M %p'))
        for self.an_index in range(int(self.number_of_qs)):
            self.an_answer = input('{} :'.format(self.questions[self.an_index].text))
            self.answers.append(self.an_answer)
            try:
                if self.an_answer == 'quit':
                    sys.exit()
                elif int(self.an_answer) == self.questions[self.an_index].answer:
                    print("Great job, that is correct. Next Question!")
                    self.correct += 1
                else:
                    print("Sorry, that answer is incorrect. Next Question...")
                    self.wrong += 1
            except ValueError:
                print("Please enter a real answer!")

I've gotten rid of one exception, but when trying to call quit I still get this exception:

Traceback (most recent call last): File "D:\MyScripts\quiz2.py", line 53, in <module> Quiz().take_quiz() File "D:\MyScripts\quiz2.py", line 34, in take_quiz sys.exit() SystemExit

I'm wondering if the issue has something to do with my system configuration

also the last 4 lines i changed to: Quiz().take_quiz()

Quiz().summary()

input(" ")

hoping that may fix it but it gives the same exception either way