Apologizes if this is simple, I just don't know what I am doing wrong.
I need to update information from a website I am scraping every 10 seconds (so as not to overload the website). I want to display the information from the website using pygame. I have tried using the threading module. However, when I make the thread sleep, it sleeps the whole program.
For example, when I do something like:
def func():
print('Hello1')
time.sleep(4)
print('Hello2')
class Display():
def __init__(self):
pg.init()
self.win = pg.display.set_mode((WIN_WIDTH,WIN_HEIGHT))
pg.display.set_caption(WIN_TITLE)
def thread_function(self):
x = threading.Thread(target = func)
x.start()
def initialize_display(self):
run = True
while run:
self.win.fill(WHITE)
self.thread_function()
for event in pg.event.get():
if event.type == pg.QUIT:
run = False
#deactivate pg library
pg.quit()
#quit program
quit()
pg.display.update()
if __name__ == "__main__":
display = Display()
display.initialize_display()
The whole program waits 4. How can I make it so only that process of func() is executed after 4 seconds?
Are you sure that you want to start a new thread every frame? Maybe just create the thread once and start another loop inside the target function of the thread, or wrap that function with another one that also handles exiting the thread gracefully.
You could do something like this:
import pygame as pg
import threading
import time
import signal
WIN_WIDTH,WIN_HEIGHT=(400,400)
WIN_TITLE=''
WHITE='white'
def func():
print('Hello1')
time.sleep(4)
print('Hello2')
class Display():
def __init__(self):
pg.init()
self.win = pg.display.set_mode((WIN_WIDTH,WIN_HEIGHT))
pg.display.set_caption(WIN_TITLE)
def thread_function(self, should_stop):
print('[Display] starting thread')
# 'func' is wrapped in this wrapper function
# the wrapper loops until the 'should_stop'-callback returns true
def wrapper(should_stop):
print('start doing something')
while not should_stop():
func()
print('stop doing something')
x = threading.Thread(target = wrapper, args = [should_stop])
x.start()
return x
def initialize_display(self):
# run could also be an attribute of Display ....
run = True
# we keep a reference of the thread to we can wait
# for it to finish once we told it to stop
thread = self.thread_function(lambda: not run)
# when the process should be killed (e.g. CTRL+C), we also want
# to stop the thead by setting 'run' to false
def stop(sig, frame):
print('[Display] got killed, stop thread')
nonlocal run
run = False
signal.signal(signal.SIGINT, stop)
# just a little moving Rect so we see the main loops works
# fine while the thread runs in the background
r = pg.Rect((0, 200, 20, 20))
d = 1
clock = pg.time.Clock()
while run:
self.win.fill(WHITE)
for event in pg.event.get():
if event.type == pg.QUIT:
# setting 'run' to false will also stop the loop
# of the wrapper function
run = False
print('[Display] waiting for thread to finish')
# let's wait for the thread to finish
thread.join()
return
pg.draw.rect(self.win, 'dodgerblue', r)
r.move_ip(d, 0)
if not self.win.get_rect().contains(r):
d *= -1
pg.display.update()
clock.tick(60)
if __name__ == "__main__":
display = Display()
display.initialize_display()