Search code examples
pythonperformancekeyboardcpuxlib

How to fix this script so that it won't peg the CPU?


On my home Kubuntu machine, I am running a script to beep on every keypress, no matter which window or application has focus, adapted from this insightful page

#!/usr/bin/env python 

from Xlib.display import Display
import os
import sys

ZERO=[]
for i in range(0,32):
        ZERO.append(0)
ignorelist=[ZERO]

def main():    
        if os.getuid()==0:
                os.system("modprobe pcspkr")
                print("Speaker enabled, start as normal user")
                sys.exit()

        print("If no beep is heard, then run as root to enable pcspkr")

        disp = Display()
        while 1:
                keymap=disp.query_keymap()
                if keymap not in ignorelist:
                        os.system("beep")

if __name__ == '__main__':
        main()

The script works great, but it pegs both CPUs of my dual-core Intel machine at around 80% each, so I can do little else with the machine. How can I reduce the CPU requirements of this simple script without interfering with its operation? In other words, it should still beep at the moment of keypress, no matter what window or application has focus.

If this is not possible in Python, what other technologies should I look at? C? I would assume that there exists some kernel component which notifies applications of keypresses: how else does KDE handle global shortcuts? How can I get my application to receive these notices as well?

The goal is to make a beep at the moment each key is pressed, as I am training my fingers to type on a mechanical keyboard without bottoming out yet without missing keypresses. I just graduated from Cherry Browns to Cherry Blues and the lack of tactical feedback takes some time to get used to.

Note that any solution must emit a beep no matter which window has focus. This program is intended to be used as a daemon that will run in the background of all applications that I use.

Thanks.


Solution

  • You can start your script using nice. The nice command will lower the priority of your script, so that it will only run when the system has nothing else to do. That way it will still eat CPU cycles, but you will be able to use your system normally for other tasks.

    See the man page for details.

    EDIT:

    To reduce CPU usage, you could add a small delay, using time.sleep(0.01). This will reduce the CPU load, but will marginally increase the time between the keypress and the resulting beep.