Reputation: 11
As a new programmer, I'm trying to create a Python3 script that creates a Countdown timer based on the KeyCombination used which is then written to a text file used by StreamlabsOBS. The idea is that when a KeyCombo is pressed (e.g ctrl+alt+z) a function starts a timer, and at the same time, another function writes the current time in the countdown to a txt file. This script would ideally be running during the entire stream.
So far, I can get the countdown working and writing to the file exactly how I want it to. But it seems the Thread is still alive after finishing the countdown. I'm not sure if this is a problem or not. Another thing is that I want to implement some kind of pause feature, that would pause the timer function. I'm not sure how to even start on that part.
The print statements are for me to know what part of the function I am at.
from pynput import keyboard
from pathlib import Path
from threading import Thread
import queue
from time import sleep
script_location = Path(__file__).absolute().parent
timer_queue = queue.Queue()
def storeInQueue(function):
print("Sent Start Thread msg")
def storer(*args):
for time in function(*args):
timer_queue.put(time)
print(f"stored {time}")
return storer
@storeInQueue
def timer(t):
print("Iterating Timer Loop")
while t > -1:
yield t
sleep(1)
t -= 1
def speakKorean():
print("starting Thread")
timer_thread = Thread(target=timer, args=(5,))
timer_thread.start()
ctime = timer_queue.get()
while ctime >-1:
with open(script_location / 'ChronoDown.txt', "w") as timer_file:
timer_file.write(f"Speak Korean for {ctime}s")
timer_file.flush()
sleep(1)
ctime = timer_queue.get()
if ctime == 0: break
print('Speak Korean done!')
with open(script_location / 'ChronoDown.txt', "w") as timer_file:
timer_file.write(f"Done!")
timer_file.flush()
while timer_thread.is_alive:
print("timer thread still running?")
timer_thread.join()
break
if timer_thread.is_alive:
print("didn't work")
def on_activate_z():
timer_file = open(script_location / 'ChronoDown.txt', "w")
timer_file.write("other keywords")
timer_file.close()
def on_activate_c():
korean_thread = Thread(target=speakKorean,)
korean_thread.start()
print("Working")
def on_activate_x():
timer_file = open(script_location / 'ChronoDown.txt', "w")
timer_file.write("No cursing for time")
timer_file.close()
with keyboard.GlobalHotKeys({
'<ctrl>+<alt>+z': on_activate_z,'<ctrl>+<alt>+c': on_activate_c,
'<ctrl>+<alt>+x': on_activate_x}) as h:
h.join()
My console output looks like this after I run it. I'm not sure why "Sent Start Thread msg" sends before I start thread too.
Sent Start Thread msg
starting Thread
Working
Iterating Timer Loop
stored 5
stored 4
stored 3
stored 2
stored 1
stored 0
Speak Korean done!
timer thread still running?
didn't work
Also if you have any optimization tips that would be appreciated. Thank you in advance for any help.
Upvotes: 0
Views: 116
Reputation: 11
Thanks to @furas , I've now implemented a pause function that properly resumes as well. This is my updated code :
from pynput import keyboard
from pathlib import Path
from threading import Thread
import queue
from time import sleep
script_location = Path(__file__).absolute().parent
timer_queue = queue.Queue()
paused = False
while paused == False:
def storeInQueue(function):
print("Sent Start Thread msg")
def storer(*args):
for time in function(*args):
timer_queue.put(time)
print(f"stored {time}")
return storer
@storeInQueue
def timer(t):
print("Iterating Timer Loop")
while t > -1:
if paused == False:
yield t
sleep(1)
t -= 1
else: continue
def speakKorean():
print("starting Thread")
timer_thread = Thread(target=timer, args=(5,))
timer_thread.start()
ctime = timer_queue.get()
while ctime >-1:
with open(script_location / 'ChronoDown.txt', "w") as timer_file:
timer_file.write(f"Speak Korean for {ctime}s")
timer_file.flush()
sleep(1)
ctime = timer_queue.get()
if ctime == 0: break
print('Speak Korean done!')
with open(script_location / 'ChronoDown.txt', "w") as timer_file:
timer_file.write(f"Done!")
timer_file.flush()
timer_thread.join()
if timer_thread.is_alive():
print("didn't work")
else: print("its dead")
def on_activate_z():
global paused
timer_file = open(script_location / 'ChronoDown.txt', "w")
timer_file.write("Paused")
timer_file.close()
if paused == True:
paused = False
print(f'Paused = {paused}')
else:
paused =True
print(f'Paused = {paused}')
def on_activate_c():
korean_thread = Thread(target=speakKorean,)
korean_thread.start()
print("Working")
def on_activate_x():
timer_file = open(script_location / 'ChronoDown.txt', "w")
timer_file.write("No cursing for time")
timer_file.close()
with keyboard.GlobalHotKeys({
'<ctrl>+<alt>+z': on_activate_z,'<ctrl>+<alt>+c': on_activate_c,
'<ctrl>+<alt>+x': on_activate_x}) as h:
h.join()
The main differences:
My entire code is now encapsulated in a While paused == False
loop, which allows me to pause my timer
function based on the state of paused
using an if
statement
I've added the missing ( )
to timer_thread.is_alive()
which allowed me to properly end the timer
Thread
Upvotes: 1