Issue with sys.exit() in pygame - python

I am learning to use Pygame, and when I use sys.exit(), I run into a problem. Here is the code:
import pygame, sys,os
from pygame.locals import *
pygame.init()
window = pygame.display.set_mode((468, 60))
pygame.display.set_caption('Game')
screen = pygame.display.get_surface()
file_name = os.path.join("data","image.bmp")
surface = pygame.image.load(file_name)
screen.blit(surface, (0,0))
pygame.display.flip()
def input(events):
for event in events:
if event.type == QUIT:
sys.exit(0)
else:
print event
while True:
input(pygame.event.get())
It's really just the code from the pygame tutorial. The problem occurs when I actually try to exit, regardless of what event I try to use to sys.exit().
Traceback (most recent call last):
File "C:/Python27/Lib/site-packages/pygame/examples/test.py", line 25, in <module>
input(pygame.event.get())
File "C:/Python27/Lib/site-packages/pygame/examples/test.py", line 20, in input
sys.exit(0)
SystemExit: 0
... And then the program doesn't exit. What am I doing wrong here? Because I did notice that this code was for an antiquated version of Python.

sys.exit()
alone is a bit unholy with pygame.. the proper way to exit a pygame app is to first break out of the mainloop then quit pygame then quit the program. ie.
while running == True:
# catch events
if event_type == quit:
running = False # breaks out of the loop
pygame.quit() # quits pygame
sys.exit()
also it seems to me that you aren't catching the event properly.. it should be
if event.type == pygame.QUIT:
you can read more about events in pygame here.

sys.exit just throws an exception (a SystemExit exception). This has two unusual effects:
It only exits the current thread in a multithreaded application
The exception could have been caught.

I solved this problem and the right code is below:
running = True
while running == True:
for event in pygame.event.get():
if event.type == QUIT:
running = False # Exiting the while loop
screen.blit(background, (0,0))
pygame.display.update()
pygame.quit() # Call the quit() method outside the while loop to end the application.

I have read in some sources there is a conflict between the mainloop() in Tkinter which runs the Python shell and Pygame.init() which the sys.exit() command follows.
The suggestion was to run the game from the command line to get round the problem rather than load the game using run (F5) from the shell.
A good side effect of this was that in my space invaders game, which does a lot of variable updating: 35 times a second, was that the animation ran correctly whereas from the shell it ran poorly and was jerky.
If i use the following code:
if event.type == QUIT:
pygame.quit()
sys.exit()
the game exits correctly but leaves an error message in the shell which has no effect on the game and is largely redundant. It is just a little ugly. This does not happen from the command line.
Summary: try running the game from the command line to avoid Tkinter problems

If you still have the issue, (after breaking the loop) try using sys.exit(0) instead of sys.exit(). Hope it'll help. It worked for me. It seems pygame expects the 'status' argument (i.e. 0 here) to be passed in explicitly.
See the below example:
isRunning = True
while isRunning:
# Catch events
if event.type == pygame.QUIT:
isRunning = False # Breaks the loop
pygame.quit()
sys.exit(0)

Related

Why doesn't the sys module run in Alien Invasion? [duplicate]

I just spent a fair amount of time finding a 64-bit installation of pygame to use with python 3.3, (here) and now am trying to make a window. However, although the window opens up fine it does not close when it hit the x button. In fact, I have to close IDLE to close the window. I am running a 64 bit version of Win 7. Here is my code:
import pygame
import time
(width, height) = (300, 200)
screen = pygame.display.set_mode((width, height))
pygame.display.flip()
pygame.display.set_caption("Hello World")
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
When I append
time.sleep(5)
pygame.quit()
It still doesn't close. My only guess would be that pygame.quit might go inside one of the loops, but even if that were resolved I would greatly prefer being able to close the window when I want to.
Most pygame tutorials seem to suggest exiting by calling pygame.quit() and then sys.exit(). I have personally run into problems (was on a unix system though) where this still did not close the window properly. The solution was to add pygame.display.quit() specifically before pygame.quit(). That should not be necessary as far as I can tell, and I'm afraid I don't know why that solved the issue but it did.
if you want to make pygame close when window button x is pressed, put the code like this:
from sys import exit
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
We put exit() after pygame.quit(), because pygame.quit() makes the system exit and exit() closes that window.
Not sure but try this Because you code runs fine on my system after I add pygame.quit() at the end
import pygame
import time
(width, height) = (300, 200)
screen = pygame.display.set_mode((width, height))
pygame.display.flip()
pygame.display.set_caption("Hello World")
running = True
try:
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
except SystemExit:
pygame.quit()
Its perhaps because as Idle is made on Tkinter and thus Tkinter and Pygame main loop do not have a mutual understanding.
Your code will run very well on command prompt though.
This was the final code that worked for me on OSX whilst keeping the kernel alive on Jupyter. EDIT - it does still crash the kernel sometimes :-(
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.display.quit()
pygame.quit()
exit()
Also needed to downgrade ipython to get rid of some magic alias warning messages using:
conda install ipython=7.2.0
apparently that issue is due to be fixed in ipython 7.6.0
Suffered the same issues on Python 3.7.4 while running it from in IDE (Spyder 3.3.6). In my case the pygame.quit() would not completely close the program.
Nonetheless, adding quit() or exit() did the trick for me!
Add this at the top:
import sys
Add this where you need to quit:
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
try using the following command:
sys.exit(0)
notice: You will need to import the sys library in order to use it.
The IDE interferes with how pygame runs the code. Try to run it from the commandline or the terminal. The problem should disappear.
To answer the original question: You must call pygame.quit() after breaking the main loop. One elegant solution goes as follows:
def run():
pygame.init()
while True:
# ...
for event in pygame.event.get():
# Handle other events
if event.type == pygame.QUIT:
return pygame.quit()

When I close PyGame window the window closes but python becomes non responsive

I wrote a game with pygame. The game works fine but when I quit and close the window, while the window does close Python itself does not quit and instead shows (not responding) and I am forced to, well, force quit.
I start the code by importing several modules
import random, pygame, sys
from pygame.locals import*
There is only one place in the code that directly commands the program to shut down
def terminate():
pygame.quit()
sys.exit()
To quit the program always runs the terminate() function.
I tried adding pygame.display.quit() above pygame.quit() and substituting raise SystemExit for sys.exit()
What could cause python to close the window but not shut down itself?
I personnay don't imoprt sys to exit. It simply isn't effective for me to type sys.exit() and you can simply call exit() to exit the program.
So you can close the window like that:
# main loop
running = True
while running:
for event in pygame.event.get():
if event.type == QUIT: # if the user closes the window
running = False
# after exiting mail loop
pygame.quit()
exit()
[EDIT] According to this answer, you should prefer using quit() instead of exit():
However, like quit, exit is considered bad to use in production code and should be reserved for use in the interpreter. This is because it too relies on the site module.
I don't get any problems now that I use quit().

Trying to understand pygame

I am having trouble trying to grasp a couple of things inside the py game code, firstly why are there two types of quit or are these the same? for example:
pygame.QUIT
pygame.quit()
Also I can't grasp this small piece code fully:
for event in pygame.event.get():
if event.type == pygame.QUIT:
I understand the first line of code, but I don't understand event.type?, is .type a function inside of pygame or python in general? what does it do?
pygame.QUIT
Is an enumeration for an input that signals for the program to quit
pygame.quit()
Is a function call to unload pygame modules. According to the docs it won't actually quit the game:
http://www.pygame.org/docs/ref/pygame.html#pygame.quit
You could use sys.exit(0) for that.
This loop here:
for event in pygame.event.get():
if event.type == pygame.QUIT:
Checks each event, if one of them has the value pygame.QUIT then some exit code should follow.
pygame.QUIT is simply a constant, while pygame.quit() is a function within the pygame module that uninitializes it. The fragment of code:
for event in pygame.event.get():
if event.type == pygame.QUIT:
...
is part of the typical control loop of a pygame program. The method pygame.event.get() returns the next event. If the type of event (an attribute of the event object) is pygame.QUIT then the application should do what is necessary to exit, including possibly calling pygame.quit().
The manual for pygame.quit() says:
Uninitialize all pygame modules that have previously been initialized. When the Python interpreter shuts down, this method is called regardless, so your program should not need it, except when it wants to terminate its pygame resources and continue.
So you should normally call this method yourself.
pygame.QUIT is a so called event type. Pygame uses events to tell you something happened. The code checks each events in the queue and checks if a QUIT event happened.
event.type is something from pygame, and it tells you what type of event it is. By comparing it to pygame.QUIT, you can check if the quit() method has been called, and take steps to shutdown the game.

Why is this tiny pygame program freezing and doing nothing?

This program infinite loops. Does nothing. Won't take input or print anything. Ideas?
import pygame
pygame.init()
running = 1
while(running):
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
print "hi"
running = 0
The problem with your script is solely that there's no window that could capture the events.
You have to create and initialize a window with pygame.display.set_mode first.
import pygame
pygame.init()
# create a window that will capture the events
pygame.display.set_mode((200, 200))
running = 1
while(running):
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
print "hi"
running = 0
Try the following:
import pygame, sys
pygame.init()
pygame.mixer.init(22050, -16, 2, 3072)
pygame.mixer.music.load("Kundara_Lake-of-Dust-320.mp3")
pygame.mixer.music.play(1, 0.0)
running = 1
while(running):
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.mixer.music.stop()
pygame.quit()
running = 0
From http://www.pygame.org/docs/ref/pygame.html
pygame.quit
Uninitialize all pygame modules that have previously been initialized. When the Python interpreter shuts down, this method is called regardless, so your program should not need it, except when it wants to terminate its pygame resources and continue. It is safe to call this function more than once: repeated calls have no effect.
Note, that pygame.quit will not exit your program. Consider letting your program end in the same way a normal python program will end.
You are looping infinitely calling pygame.quit() due to while(1).
You need to update the screen. Try it with
screen = pygame.display.set_mode((640,360),0,32)
and in the loop, write
pygame.dispay.flip()
to close the window completely, you can use
sys.exit()
just be sure to include sys in your imports
pygame does not recognize the term 'input' or 'print'. It would be a lot simpler if it did!! Instead, to get text onto the screen, you must use 'drawText('message',font,surface,(xpos,ypos) putting your own text in 'message', your own surface name in 'surface' and the x and y co-ordinates in 'xpos' and 'ypos'.

Playing music with Pygame unreliable

I'm trying to write a simple program to play music files with Pygame. My script is below.
import pygame
import sys
import time
FRAMERATE = 30
if len(sys.argv) < 2:
sys.exit(2)
filename = sys.argv[1]
clock = pygame.time.Clock()
pygame.init()
pygame.mixer.init(frequency=44100)
pygame.mixer.music.load(filename)
print "%s loaded!" % filename
pygame.mixer.music.play(1)
while pygame.mixer.music.get_busy():
clock.tick(FRAMERATE)
But I'm having some puzzling problems. The "[File name] loaded!" message always prints, but sometimes it never enters the loop and exits immediately. If I check on the status of pygame.mixer.music.get_busy(), it appears to be false immediately after the pygame.mixer.music.play(1) command. This happens erratically; I just tried running the program with no changes to the code, having it work once and encounter this problem once right afterward. Does anyone know what could be causing these seemingly random playback problems?
I imagine this is because the actual music playback is happening on another thread, so it sometimes hasn't finished starting at the point you first call get_busy().
If that's the case, it seems like a bug in either pygame or SDL_mixer (which pygame uses.)
As an alternative way of checking for music completion, you can get pygame to give you an event when the music finishes and check for that. Like this:
pygame.mixer.music.set_endevent(pygame.USEREVENT)
quit = False
while not quit:
clock.tick(FRAMERATE)
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit = True
if event.type == pygame.USEREVENT:
print "Music ended"
quit = True

Categories