Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 510
dotancohen Avatar asked Aug 16 '12 15:08

dotancohen


2 Answers

Use events:

import Xlib
from Xlib.display import Display

display = Display()

screen = display.screen()
w = screen.root.create_window(0, 0, 100, 100, 1,
              screen.root_depth,
              event_mask = Xlib.X.KeyPressMask)
w.map()

while True:
    event = display.next_event()
    if event.type != Xlib.X.KeyPress:
        continue
    print "OHAI"

Details cadged from http://python-xlib.sourceforge.net/doc/html/python-xlib_10.html#SEC9

like image 189
Iain Avatar answered Sep 22 '22 18:09

Iain


Your while loop is consuming all your CPU's cycles since it's executing as fast as possible. You could add a small sleep() delay, but you risk missing out on some key events. Alternatively, consider using the pyhook module to monitor key presses.

like image 40
Lanaru Avatar answered Sep 19 '22 18:09

Lanaru