Python CTRL-C exit without traceback?
-
02-07-2021 - |
Question
Building a simple Python game of "Rock, Paper, Scissors" for learning purposes.
I've read some other posts here on exiting from Python without a traceback. I'm trying to implement it but still getting a traceback! Can some Python wiz point out what's wrong for this Python dummy? The idea is that clicking RETURN (or typing "yes" or "y" will make the program run the play() again, but hitting CTRL-C will close it without a traceback. I´m using Python 2.7.
# modules
import sys, traceback
from random import choice
#set up our lists
ROCK, PAPER, SCISSORS = 1, 2, 3
names = 'ROCK', 'PAPER', 'SCISSORS'
#Define a function for who beats who?
def beats(a, b):
return (a,b) in ((PAPER, ROCK), (SCISSORS, PAPER), (ROCK, SCISSORS))
def play():
print "Please select: "
print "1 Rock"
print "2 Paper"
print "3 Scissors"
# player choose Rock, Paper or Scissors
player_choice = int(input ("Choose from 1-3: "))
# assigns the CPU variable a random CHOICE from a list.
cpu_choice = choice((ROCK, PAPER, SCISSORS))
if cpu_choice != player_choice:
if beats(player_choice, cpu_choice):
print "You chose %r, and the CPU chose %r." % (names[player_choice - 1], names[cpu_choice - 1])
print "You win, yay!!"
else:
print "You chose %r, and the CPU chose %r." % (names[player_choice - 1], names[cpu_choice - 1])
print "You lose. Yuck!"
else:
print "You chose %r, and the CPU chose %r." % (names[player_choice - 1], names[cpu_choice - 1])
print "It's a tie!"
print "Do you want to play again? Click RETURN to play again, or CTRL-C to exit!"
next = raw_input("> ")
# THIS IS WHAT I'M WORKING ON - NEED TO REMOVE TRACEBACK!
if next == "yes" or "y":
try:
play()
except KeyboardInterrupt:
print "Goodbye!"
except Exception:
traceback.print_exc(file=sys.stdout)
sys.exit(0)
elif next == None:
play()
else:
sys.exit(0)
# initiate play() !
play()
Solution
You call play()
twice, so you need to put both cases in a try
/except
block:
if next in ("yes", "y"):
try:
play()
except KeyboardInterrupt:
print "Goodbye!"
except Exception:
traceback.print_exc(file=sys.stdout)
sys.exit(0)
elif next is None:
try:
play()
except KeyboardInterrupt:
print "Goodbye!"
except Exception:
traceback.print_exc(file=sys.stdout)
sys.exit(0)
else:
sys.exit(0)
I've corrected two other problems, it is better to test for None
with is
in python, and your first if
test was not going to work, as next == "yes" or "y"
is interpreted as next == "yes"
separately from "y"
with an or
in between. The "y"
is always seen as True
so you never would come to the other branches in your code.
Note that I suspect the above code could be simplified much more, but you don't show us your play()
function at all, so you leave us to guess what you are trying to do.
OTHER TIPS
Try restructuring your main loop; something more along the lines of:
try:
while (play()):
pass
except KeyboardInterrupt:
sys.exit(0)
And play
looks like:
def play():
_do_play() # code for the actual game
play_again = raw_input('play again? ')
return play_again.strip().lower() in ("yes", "y")
One problem is that you need to enclose your raw_input
statement in a try
except KeyboardInterrupt
clause as well as the actual play
function. e.g.
try:
nxt = raw_input('>')
if nxt.lower().startswith('y') or (nxt.strip() == ''):
play()
else:
sys.exit(0)
except KeyboardInterrupt:
sys.exit(0)
except Exception:
traceback.print_exc(file=sys.stdout)