Home > Back-end >  Key-listener that Runs Concurrently With a Terminal Timer using Threads
Key-listener that Runs Concurrently With a Terminal Timer using Threads

Time:08-12

I am trying to make a timer that runs concurrently with a key-listener. The key-listener should perform a function when it takes a key and stop the timer. Below is the code I wrote. Though when I run it, the timer runs infinitely but the the key-listener does not listen for keys thus not print what it's supposed to.

Nota bene I am just getting into threading so the whole code I have written may be logically wrong in the paradigm of threading.

import concurrent.futures
import time
import os
import keyboard

run_timer = True
keep_scanning = True

def startTimer(seconds):
    while run_timer:
        for i in range(1, seconds):
            print(i)
            time.sleep(1)
            os.system("clear")
            
def scanForInput():
    while keep_scanning:
        print(keep_scanning)
        if keyboard.is_pressed('space'):
            keep_scanning = False
            run_timer = False
            return "HIT"
            
with concurrent.futures.ThreadPoolExecutor() as executor:
    f1 = executor.submit(startTimer, 4)
    f2 = executor.submit(scanForInput) 

CodePudding user response:

It was hard to debug. Your scanForInput func terminating because keyboard library raise ImportError('You must be root to use this library on linux.') error when you have no root privileges, this is specified in the doc. The bad thing is ThreadPoolExecutor thread not log this error to stdout or stderr directly if we don't catch this error. I did some debug that this function is really working, and I have see that this function terminating after the print(keep_scanning) command, because i had no root privileges. So, to be able to use keyboard library in Linux, we need to have sudo(root) privileges.

And second thing, you need to use global keyword to be able to update the keep_scanning and run_timer variables in the scanForInput function, but using global keyword is not good practice.

you can update your code like this :

import concurrent.futures
import time
import os,threading
import keyboard

run_timer = True
keep_scanning = True

def startTimer(seconds):
    while run_timer:
        for i in range(1, seconds):
            print(i)
            time.sleep(1)
            os.system("clear")
            
def scanForInput():
    global keep_scanning,run_timer
    try:
        while keep_scanning:
            print(keep_scanning)
            if keyboard.is_pressed('space'):
                keep_scanning = False
                run_timer = False
                return "HIT"
    except Exception as e:
        print(e)
        
with concurrent.futures.ThreadPoolExecutor() as executor:
    f1 = executor.submit(startTimer, 4)
    f2 = executor.submit(scanForInput)

and you need to run this command with sudo privileges like sudo python3 mycode.py

  • Related