0

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.

4
  • if you need pause then you should use global variable paused = False and run code in while True, if not paused: .. code ... - and when you change paused = True then it will skip code, and if you set again paused = True then it will run code. Commented Jun 12, 2021 at 4:26
  • while timer_thread.is_alive: ... break seems weird - you could write it using if without break Commented Jun 12, 2021 at 4:29
  • you forgot () in function is_alive() - in two places. Commented Jun 12, 2021 at 4:31
  • @furas Thank you for your help so far! I hadn't realized that is_alive needed the () and that fixed the check and properly ended the Thread. The Pausing Method you proposed also worked beautifully. Thank you for your help! Commented Jun 12, 2021 at 5:04

1 Answer 1

1

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:

  1. 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

  2. I've added the missing ( ) to timer_thread.is_alive() which allowed me to properly end the timer Thread

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.