I'm creating a Mad Libs game that has a lot of user inputs. I created a function to get all inputs in a list, given a list of the word types. There's no error message, but the window is blank. I tried printing the wordInputs list, and it comes up with:
[<bound method StringVar.get of <tkinter.StringVar object at 0x108763fd0>>,
and so forth. I presume this is because it deleted all of the widgets, but I figured it would do that only after I typed them in. I'm not exactly sure how to store the input into a variable either; do I create a button for that or something? Here's the code:
from tkinter import *
class Game:
#Gets user input for a specified type of word
def getWord(self, words):
wordInputs = []
for i in range(len(words)):
frame = Frame(self.windowSnowDay)
frame.pack()
Label(frame, text = "\nSnow Day\n________\n").grid(row = 1, column = 1, columnspan = 2)
Label(frame, text = "Enter a(n) " + words[i] + ":").grid(row = 2, column = 1)
word = StringVar()
Entry(frame, textvariable = word).grid(row = i + 2, column = 2)
wordInputs.append(word.get)
frame.destroy()
return wordInputs
#Executes "Snow Day" story from Mad Libs menu
def snowDay(self):
self.windowMadLibs.destroy()
self.windowSnowDay = Tk()
self.windowSnowDay.title("Snow Day")
self.windowSnowDay.geometry("200x200")
frame = Frame(self.windowSnowDay)
frame.pack()
#Collects words and stores them in a list
words = ["verb", "electronic device", "public place", "adjective", "verb ending with -ing", "color", "noun", "noun", "drink", \
"clothing item", "adjective", "3-dimensional shape", "adjective", "plural noun", "adjective", "feeling (adjective)", "food"]
wordInputs = self.getWord(words)
print(wordInputs)
self.windowSnowDay.mainloop()
#Prints "Snow Day" story with all inputted words
print("\nAll the children cheer in", emotion, "as they", verb, "that morning. They hear on the", device,"that the", place, end =' ')
print("is closed because of a snowstorm. They think of all the", adj, "things they could do today, such as", verb1, "on a", end = ' ')
print(color, noun + ". Maybe they can even make a snow" + noun1 + "! They go inside, where a warm cup of", drink, "awaits", end = ' ')
print("them. Before going outside, they put on their scarves and", clothing, "so that they don't get", adj1 + ". They", end = ' ')
print("make a snow" + noun1, "out of 3 large", shape + "s, but it quickly fell apart because the snow wasn't very", adj2, end = '. ')
print("After that, one of the", noun2, "attacked another, and it turned into a", adj3, "snowball fight. They were so", feeling, end = ' that ')
print("they went straight to bed. Oh well, I guess they can eat the leftovers of Mom's famous", food, "tomorrow!")
#Main function for Mad Libs
def madLibs(self):
self.windowMadLibs = Tk()
self.windowMadLibs.title("Mad Libs")
self.windowMadLibs.geometry("200x200")
frame = Frame(self.windowMadLibs)
frame.pack()
Label(frame, text = "\nMad Libs\n________\n").grid(row = 1, column = 1)
Button(frame, text = "Snow Day", command = self.snowDay).grid(row = 2, column = 1)
self.windowMadLibs.mainloop()
The main issue is it does not wait for user input, so it's basically going through the loop with all blank values in the entry, then nothing is filled.
(See my comments in the code for more detail)
The bound method StringVar.get result is from wordInputs.append(word.get) instead of wordInputs.append(word.get())
Also, multiple Tk() and .mainloop() calls tend to gum up the works.
This will get it going again, but window re-sizing will need to be addressed,
The prints reference variables that will need to be filled in, you may want a dictionary versus a list:
from tkinter import *
class Game:
#Gets user input for a specified type of word
def getWord(self, words):
wordInputs = []
for i in range(len(words)):
frame = Frame(self.windowSnowDay)
frame.pack()
Label(frame, text = "\nSnow Day\n________\n").grid(row = 1, column = 1, columnspan = 2)
Label(frame, text = "Enter a(n) " + words[i] + ":").grid(row = 2, column = 1)
word = StringVar()
entry = Entry(frame)
entry.grid(row = i + 2, column = 2)
button = Button(frame, text = "Done", command = lambda: word.set(entry.get()))
button.grid(row = i + 3, column = 2)
button.wait_variable(word) # waits for button to be activated and sets the variable.
wordInputs.append(word.get())
frame.destroy()
return wordInputs
#Executes "Snow Day" story from Mad Libs menu
def snowDay(self):
self.windowMadLibs.withdraw() # withdraw the main window.
self.windowSnowDay = Toplevel(self.windowMadLibs) # create a Toplevel instead of a new main.
self.windowSnowDay.title("Snow Day")
self.windowSnowDay.geometry("200x200")
frame = Frame(self.windowSnowDay)
frame.pack()
#Collects words and stores them in a list
words = ["verb", "electronic device", "public place", "adjective", "verb ending with -ing", "color", "noun", "noun", "drink", \
"clothing item", "adjective", "3-dimensional shape", "adjective", "plural noun", "adjective", "feeling (adjective)", "food"]
wordInputs = self.getWord(words)
print(wordInputs)
#Prints "Snow Day" story with all inputted words
print("\nAll the children cheer in", emotion, "as they", verb, "that morning. They hear on the", device,"that the", place, end =' ')
print("is closed because of a snowstorm. They think of all the", adj, "things they could do today, such as", verb1, "on a", end = ' ')
print(color, noun + ". Maybe they can even make a snow" + noun1 + "! They go inside, where a warm cup of", drink, "awaits", end = ' ')
print("them. Before going outside, they put on their scarves and", clothing, "so that they don't get", adj1 + ". They", end = ' ')
print("make a snow" + noun1, "out of 3 large", shape + "s, but it quickly fell apart because the snow wasn't very", adj2, end = '. ')
print("After that, one of the", noun2, "attacked another, and it turned into a", adj3, "snowball fight. They were so", feeling, end = ' that ')
print("they went straight to bed. Oh well, I guess they can eat the leftovers of Mom's famous", food, "tomorrow!")
#Main function for Mad Libs
def madLibs(self):
self.windowMadLibs = Tk()
self.windowMadLibs.title("Mad Libs")
self.windowMadLibs.geometry("200x200")
frame = Frame(self.windowMadLibs)
frame.pack()
Label(frame, text = "\nMad Libs\n________\n").grid(row = 1, column = 1)
Button(frame, text = "Snow Day", command = self.snowDay).grid(row = 2, column = 1)
self.windowMadLibs.mainloop()
g = Game()
g.madLibs()
Related
my problem is the programme won't state the answer as correct only if you put the answer alone, but i want to make that you can actually put a phrase in the entry widget and if the answer is in that phrase it would say correct, i made this work without tkinter but i canno't make it work in tkinter here is my code, could you please help, thanks.
the code
import tkinter as tk
from time import sleep
win = tk.Tk()
win.title("Learning game")
class Question:
def __init__(self,prompt,answer):
self.answer = answer
self.prompt = prompt
score = 0
def ask():
global questions
global useranwser
global score
if questions:
#Check both the possible answers
if useranwser.get() in questions[0].answer:
print("Correct")
score += 1
else:
print("Incorrect")
questions.pop(0)
if questions:
s.set(questions[0].prompt)
else:
print('Done')
print("Your score is : ",score)
quit() #optional
useranwser.set('')
question_prompts = [
"When did Tunisia gain independence? \n 1956 , 1984 , 1965 \n", "What is the captial of tunis ? \n Tunis, Gafsa, Nabuel \n",
"Who won 2018 football world cup ? \n Italy, France, England \n","how long is the eiffel tower ?\n 324m, 354m, 412m \n",
"What is the heaviest metal \n Iron, Copper, Uraniam \n "
]
questions = [
Question(question_prompts[4], "uraniam"),
Question(question_prompts[0], "1956"),
Question(question_prompts[1], "tunis"),
Question(question_prompts[2], "france"),
Question(question_prompts[3], "324m")
]
s = tk.StringVar()
useranwser = tk.StringVar()
q = tk.Label(win,textvariable = s)
q.grid(row = 0, column = 0)
u_answer = tk.Entry(win, textvariable = useranwser)
u_answer.grid(row = 1, column = 0)
b = tk.Button(win, text ="Submit", command = ask)
b.grid(row = 2, column =0 )
s.set(questions[0].prompt)#Set the initial question
win.mainloop()
I had to flip this if statment from this :
if useranwser.get() in questions[0].answer:
print("Correct")
score += 1
to this:
if questions[0].answer in useranwser.get():
print("Correct")
score += 1
Thanks to #justin ezequiel for the solution and #random davis for a debugging tip
Hi I'm a beginner in Python and I'm working on a chatbot interface using tkinter. The problem i'm having is that I can't seem to type in the window after asking “Hi there, what’s your name?”. Instead, the conversation continues to the next line, stating Hi (the first entry stated) would you like to purchase a ticket?
Is there a way to allow user to enter their name, then after that, state the entry?
For example:
User: Hi
Bot: Hi there, what’s your name?
User: Tom
Bot: Hi Tom, would you like to purchase a ticket?
At the moment the program goes like this:
User: hi
Bot: Hi there, what’s your name?
Bot: Hi hi would you like to purchase a ticket?
I'm not sure what is causing the Bot to state another statement, before allowing user input, I've thought of storing name in name_var using StringVar(), then use that variable in the next line, but that didn't work.. any ideas how to fix this?
This is the code I have so far:
# Representing the parent window
root = Tk()
#Title of window
root.title('Chatbot')
#Function to send the message
def send():
send = "You =>" + entry.get()
text.insert(END, "\n" + send) if(entry.get()=="Hi" or entry.get()=="hi" or entry.get()=="Hi there" or entry.get()=="hi there" or entry.get()=="Hello" or entry.get()== "hello"):
text.insert(END, "\n" + "Bot => Hi there, whats your name ?")
name_var = str(StringVar())
text.insert(END, "\n" + "Bot => Hi " + name_var + " would you like to purchase a ticket?")
else:
text.insert(END, "\n" + "Bot => Sorry, I have no answer")
entry.delete(0, END) text = Text(root)
# Adding dimensions and send button of window
text.grid(row=0, column=0, columnspan=2)
entry = Entry(root, width=100)
send = Button(root, text="Send", command=send).grid(row=1, column=1) entry.grid(row=1, column=0)
root.mainloop()```
In your send callback, you just add the two messages right after another, without waiting for user input in between. Instead, you could split that in two: A generator function, yielding the next line in a complex conversation tree, and the send message just caring about putting that next message into the text field:
from tkinter import *
def message_generator():
if entry.get().lower() in ("hi", "hi there", "hello"):
# ask for name
yield "Hi there, whats your name ?"
# greeting with name
name_var = entry.get()
yield "Hi " + name_var + " would you like to purchase a ticket?"
# more conversation, possibly with diverging branches
# if entry.get() == "yes": ...
else:
yield "Sorry, I have no answer"
def send():
text.insert(END, "\nYou =>" + entry.get())
text.insert(END, "\nBot =>" + next(msg_gen))
entry.delete(0, END)
msg_gen = message_generator()
root = Tk()
root.title('Chatbot')
text = Text(root)
text.grid(row=0, column=0, columnspan=2)
entry = Entry(root, width=100)
entry.grid(row=1, column=0)
Button(root, text="Send", command=send).grid(row=1, column=1)
root.mainloop()
The main point here is that the message_generator will not be executed fully. When you first call the function, it just creates a generator instance; then when you call next in send, it executes the generator function up to the next yield statement and pauses there, picking up execution from that same point the next time next is called, thus providing a nice way to keep track of the current state of the conversation.
I am working on a hangman game for a couple days. I am currently making the functions. I've researched how to pass a local variable to another function, but it doesn't seem to be working. I am assuming the problem is with theme = start(). When I run the program it completely ignores what the user enters as the theme and go straight to the else statement and prints "That wasn't an option" even if the user types in one of the options correctly. How can I get python to realize that the theme in def sub_theme() is History(or whatever the user types in but in this case I'm just using history) and to then continue from there?
def start():
print("Welcome to hangman!!!")
print("Let's get started.")
theme = input("Okay I'll pick a word, all you have to do is pick a theme :) \n Themes to pick from: History, Companies, Geography, Music, Movies, Celebrities, and Sports Team! ")
return theme
def sub_theme():
#### If the user chooses History as their option ####
theme = start()
if theme.casefold() == 'History':
print("So your options are: Presidents or Vice Presidents.")
user_theme = input("So what's your choice? ")
if user_theme.casefold() == "Presidents":
secret_word = "George Washington"
print(secret_word)
print(secret_word)
#### if they type in something besides the options ####
else:
print("That wasn't an option.")
return
def hide_word():
#hides the word with underscores
hide = ""
secret_word = sub_theme()
for letter in secret_word:
if letter in [" " , "," , ":" , "'" , "-" , "_" , "&" , "é", '"', "/" , "." , "?" , "!"]:
hide = hide + letter
else:
hide = hide + "_ "
print(hide)
return(hide)
def play():
hide_word()
play()
First of all, string.casefold() == "History" will never be true because casefold acts as a lower but more aggressive. Just change "History" to "history" and it'll work.
Second, you might want to look into classes.
That way you can make theme (or anything else, in this case secret_word) a self attribute and access it from all functions of your class without having to pass it between them.
Here's a quick working mookup of conversion for the code you provided:
class Hangman:
def __init__(self):
print("Welcome to hangman!!!")
print("Let's get started.")
theme = input("Okay I'll pick a word, all you have to do is pick a theme :) \n"
"Themes to pick from: History, Companies, Geography, Music, Movies, "
"Celebrities, and Sports Team! ")
if theme.casefold() == 'history':
print("So your options are: Presidents or Vice Presidents.")
user_theme = input("So what's your choice? ")
if user_theme.casefold() == "presidents":
self.secret_word = "George Washington"
else:
print("That wasn't an option.")
return
self.hide_word()
def hide_word(self):
hide = ""
for letter in self.secret_word:
if letter in [" " , "," , ":" , "'" , "-" , "_" , "&" , "é", '"', "/" , "." , "?" , "!"]:
hide = hide + letter
else:
hide = hide + "_ "
print(hide)
Hangman()
When trying to run my code, I am presented with a TypeError.
It states: TypeError:'in'requires string as left operand, not method.
I am not sure what this means exactly, or how to fix it.
The code the error is created in is:
from tkinter import *
from tkinter import messagebox
def saveCustomer() :
ClientID = ClientIDVar.get()
ClientID = ClientID.ljust(50)
Surname = SurnameVar.get()
Surname = Surname.ljust(50)
Forename = ForenameVar.get()
Forename = Forename.ljust(50)
Age = AgeVar.get()
Age = Age.ljust(50)
Gender = GenderVar.get()
Gender = Gender.ljust(50)
#lengthcheck
ClientID = ClientIDVar.get()
if len(ClientID) > 5 :
messagebox.showerror("Error","Too many characters in ClientID")
return
Surname = SurnameVar.get()
if len(Surname) > 20 :
messagebox.showerror("Error","Too many characters in Surname")
return
Forename = ForenameVar.get()
if len(Forename) > 15 :
messagebox.showerror("Error","Too many characters in Forename")
return
Age = AgeVar.get()
if len(Age) > 2 :
messagebox.showerror("Error","Too many characters in Age")
return
Gender = GenderVar.get()
if len(Gender) > 2 :
messagebox.showerror("Error","Too many characters in Gender")
return
#presencecheck
if ClientID == "":
messagebox.showerror("Error","Please enter characters into ClientID")
return
if Surname == "":
messagebox.showerror("Error","Please enter characters into Surname")
return
if Forename == "":
messagebox.showerror("Error","Please enter characters into Forename")
return
if Age == "":
messagebox.showerror("Error","Please enter characters into Age")
return
if Gender == "":
messagebox.showerror("Error","Please enter characters into Gender")
return
#rangecheck
if (int(Age) < 18) or (int(Age) > 99):
messagebox.showerror("Error","Please enter an age between 18 and 99")
return
#typecheck
if not ClientID.isnumeric():
messagebox.showerror("Error","Please enter alphabetical characters and numerical values into ClientID")
return
if not Surname.isalpha():
messagebox.showerror("Error","Please enter alphabetical characters into Surname")
return
if not Forename.isalpha():
messagebox.showerror("Error","Please enter alphabetical characters into Forename")
return
if not Age.isnumeric():
messagebox.showerror("Error","Please enter numerical values into Age")
return
if not Gender.isalpha():
messagebox.showerror("Error","Please enter alphabetical characters and numerical values into Gender")
return
#open the file to append - if it's not there it'll be created
fileObject = open("Customers.txt","a")
# write to the file with a newline character at the end
fileObject.write(ClientID + Surname + Forename + Age + Gender + "\n")
fileObject.close()
return
def searchCustomer() :
Found = "N"
ClientID = ClientIDVar.get
# try opening the file for reading
try:
fileObject=open("Customers.txt","r")
# if it's not there then say
except IOError:
messagebox.showerror("Error","No file to read")
# if we did open it then let's carry on!
else:
while True:
recordVar=fileObject.readline()
# Python keeps reading till EOF then returns a blank
if recordVar=="":
fileObject.close()
break
if ClientID in recordVar[0:50] and not ClientID=="" :
Found = "T"
messagebox.showinfo("Information",str(RecordVar))
break
if Found == "F":
messagebox.showerror("Error","No Customer found.")
return
def makeWindow():
#declared my globals here as this is the 1st routine called
# the other routines have to be in front of this one as they get called by it
# and the parser would get upset if they weren't there
global ClientIDVar, SurnameVar, ForenameVar, AgeVar, GenderVar
#here's my window
win = Tk()
win.wm_title("FitnessCentre")
#split into two sections then further split into a grid
frame1=Frame(win)
frame1.pack()
Label(frame1, text="Fitness Leisure Centre", font=("Helvetica 12 bold")).grid(row=0, column=0)
Label(frame1, text="ClientID").grid(row=1, column=0, sticky=W)
ClientIDVar=StringVar()
title= Entry(frame1, textvariable=ClientIDVar)
title.grid(row=1,column=1,sticky=W)
Label(frame1, text="Surname").grid(row=2, column=0, sticky=W)
SurnameVar=StringVar()
genre= Entry(frame1, textvariable=SurnameVar)
genre.grid(row=2,column=1,sticky=W)
Label(frame1, text="Forename").grid(row=3, column=0, sticky=W)
ForenameVar=StringVar()
director= Entry(frame1, textvariable=ForenameVar)
director.grid(row=3,column=1,sticky=W)
Label(frame1, text="Age").grid(row=4, column=0, sticky=W)
AgeVar=StringVar()
leadactor= Entry(frame1, textvariable=AgeVar)
leadactor.grid(row=4,column=1,sticky=W)
Label(frame1, text="Gender").grid(row=5, column=0, sticky=W)
GenderVar=StringVar()
duration= Entry(frame1, textvariable=GenderVar)
duration.grid(row=5,column=1,sticky=W)
frame2 = Frame(win)
frame2.pack()
# build my buttons in the other frame then pack them side by side
b1= Button(frame2, text=" Save ", command=saveCustomer)
b2= Button(frame2, text=" Search ", command=searchCustomer)
b1.pack(side=LEFT); b2.pack(side=LEFT)
return win
#main program!
win = makeWindow()
win.mainloop()
The complete error message I received was:
Exception in Tkinter callback
Traceback (most recent call last):
if ClientID in recordVar[0:50] and not ClientID=="" :
TypeError: 'in <string>' requires string as left operand, not method
Quoting from question:
TypeError: 'in' requires string as left operand, not method.
So somewhere you are using the in operator with a method on the left, not a string as expected. Had you posted the entire error/stack trace (as you should have done) we might have seen which line is causing the error. With a quick scan of your code I'd guess the error is here:
ClientID = ClientIDVar.get
Presumably you wanted to return the value of the ClientIDVar, not its get method (which is what you got). So it's a simple fix -- call the function properly:
ClientID = ClientIDVar.get()
You can't use an method to test an in comparison, you have to compare with a string:
if ClientID in recordVar[0:50] and not ClientID=="" :
The error that you get are clearly explaining this to you:
TypeError. It states: TypeError:'in'requires string as left operand, not method.
Here is a rough example of a multiple choice test that I made. It runs in terminal and I'm hoping to make a Graphical User Interface for it using Tkinter.
print "CATEGORY 1: ANXIOUS FEELINGS"
print
print "1. Anxiety, nervousness, worry or fear"
BAI_var1 = input ("Please enter 0 for not at all, 1 for somewhat, 2 for moderatly or 3 for a lot:")
print
print "2. Feeling that things around you are strange, unreal, or foggy"
BAI_var2 = input ("Please enter 0 for not at all, 1 for somewhat, 2 for moderatly or 3 for a lot:")
print
print "3. Feeling detached from all or part of your body"
BAI_var3 = input ("Please enter 0 for not at all, 1 for somewhat, 2 for moderatly or 3 for a lot:")
print "Depression Test"
print
print
print "1. Sadness: Have been feeling sad or down in the dumps?"
BDC_var1 = input ("Please enter 0 for not at all, 1 for somewhat, 2 for moderatly or 3 for a lot:")
print
print "2. Discouragement: Does the future look hopeless?"
BDC_var2 = input ("Please enter 0 for not at all, 1 for somewhat, 2 for moderatly or 3 for a lot:")
print
print "3. Low self-esteem: Do you feel worthless or think of yourself as a failure?"
BDC_var3 = input ("Please enter 0 for not at all, 1 for somewhat, 2 for moderatly or 3 for a lot:")
#Burns Anxiety Inventory
#CATEGORY 1: ANXIOUS FEELINGS
Cat1_var = BAI_var1 + BAI_var2 + BAI_var3
#Burns Anxiety Checklist
BAI_var = Cat1_var
#Burns Depression Checklist
BDC_var = BDC_var1 + BDC_var2 + BDC_var3
#Prints your BAI & your BDC
print "Your BAI =", BAI_var,"Your BDC =", BDC_var
name = raw_input ("Please type in your name:")
bai = str(input("Please enter your BAI:"))
bdc = str(input("Please enter your BDC:"))
year = str(input("please enter the year:"))
month = str(input("Please enter the month:"))
day = str(input("Please enter day:"))
time_hour = str(input("Please enter the current hour:"))
time_minute = str(input("Please enter the current minutes:"))
am_pm = raw_input ("Please enter pm or am:")
file = open('Burns inventory 1.3.txt', 'a')
file.write(name + '\n')
file.write(day)
file.write("/")
file.write(month)
file.write("/")
file.write(year)
file.write('\n')
file.write('\n')
file.write('Your BAI is:')
file.write(bai)
file.write('\n')
file.write('Your BDC is:')
file.write(bdc)
file.write('\n')
file.write(time_hour)
file.write(':')
file.write(time_minute)
file.write('\n')
file.write(' ')
file.write(am_pm)
file.write('\n')
file.close()
I have been working for 2 days two teach myself how to use Tkinter. My friend and I made this rough example of what the test might look like.
from Tkinter import *
import time
class App:
def __init__(self, master):
w = Label(master, text="1. Anxiety, nervousness, worry or fear")
w.pack()
v = IntVar()
Radiobutton(master, text="0 for not at all", variable=v, value=1).pack(side=TOP, anchor="w")
Radiobutton(master, text="1 for somewhat", variable=v, value=2).pack(side=TOP, anchor="w")
Radiobutton(master, text="2 for moderatly", variable=v, value=3).pack(side=TOP, anchor="w")
Radiobutton(master, text="3 for a lot", variable=v, value=4).pack(side=TOP, anchor="w")
self.button = Button(master, text="BACK", fg="red", command=self.button6)
self.button.pack(side=BOTTOM)
self.button = Button(master, text="NEXT", fg="red", command=self.button5)
self.button.pack(side=BOTTOM)
def button6(self):
print "Sam is awesome!GAJONGA"
def button5(self):
print "PYTHON FOR THE WIN! GIAN SAYS PYTHON = FILTHY"
master = Tk()
app = App(master)
master.mainloop()
I can think of a few goals with this Tkinter GUI:
Make Radiobuttons assign either a 0,1,2 or 3 to my variables(BAI_var1, BAI_var2, BAI_3 etc.)
Make the "NEXT" & "BACK" buttons show a different question every time you press it.
Make a page at the end of the test that has multiple input fields for name, date, etc.
I did not make the test!! I only made the software. The test was designed by David Burns and is available in his work book "The Feeling Good Book".
change all of the places where you have v with self.v so that it becomes an attribute of the object. You'll then see that it has whatever value is selected in the group of radiobuttons.
...
self.v = IntVar()
...
Radiobutton(master, text="1 for somewhat", variable=self.v, value=2)...
...
Once you do that, in your button5 or button6 method you can do print self.v.get() to see the value.
If you're not interested in learning tkinter right now, easygui would be a good fit for quickly getting a GUI for this test. It's not in the standard library, so you'll have to either install it with pip install or download it and put the easygui.py file in the same folder as your script. Easygui lets you do things like:
import easygui
animal = easygui.choicebox(
msg='Pick an animal.',
title='answer the question',
choices=('dog', 'cat', 'pig')
)
print animal
# prints dog or pig or cat