How to fix this script so that it does not bind the CPU?

On my Kubuntu home machine, I run a script to give a beep every time a key is pressed, 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 fine, but it binds both processors to my Intel dual-core machine for about 80%, so I can work a little with the machine. How can I reduce the processor requirements of this simple script without interfering with its operation? In other words, it should still sound when you press a key, regardless of which window or application has focus.

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

The goal is to make a sound at the moment each key is pressed , as I train my fingers to type a mechanical keyboard without a bottom, but without missed keystrokes. I just graduated from Cherry Browns before Cherry Blues, and the lack of tactical feedback takes some time to get used to.

Please note that any solution should emit a beep no matter which window has focus. This program is intended to be used as a daemon that will work against all the applications that I use.

Thanks.

+6
source share
5 answers

You can run your script with nice. A character command will reduce the priority of your script so that it will only work when the system has nothing more to do. Thus, it will still consume processor cycles, but you can use your system for other tasks.

See the man page for more details.

EDIT:

To reduce CPU usage, you can add a little delay using time.sleep (0.01). This will reduce the load on the processor, but will slightly increase the time between pressing a key and the resulting sound signal.

+5
source

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 related to http://python-xlib.sourceforge.net/doc/html/python-xlib_10.html#SEC9

+12
source

Your while loop consumes all your processor cycles as it runs as fast as possible. You can add a little sleep delay (), but you run the risk of missing out on some key events. Alternatively, consider using the pyhook module to control keystrokes.

+8
source

Your program starts the CPU because it runs an infinite loop that will keep your processor in a state to check the status of the keyboard every millisecond or even so, even if no keys are pressed. Since your computer does not have an indication that it may stop, it will continue to scan as often as possible, thereby burning resources.

As Ian suggested, the most elegant solution to this problem is to use Display.next_event() , which tells the program to wait until a new event is received (for example, a click). During this wait time, your program will not consume a significant amount of CPU, and your load should decrease sharply.

+5
source

Working with this answer to a previously published question , you will see a Python module called pyxhook , which is part of a program called pykeylogger .

Using this pyxhook module, you should be able to beep every time you press a key with the following code:

 import pyxhook import time import os import sys def do_beep(event): os.system('beep') hm = pyxhook.HookManager() hm.HookKeyboard() hm.KeyDown = do_beep hm.start() while True: try: time.sleep(10) except: break hm.cancel() 

I cannot test it correctly because I do not have a beep command. However, it tells sh: beep: command not found for each keystroke.

+4
source

Source: https://habr.com/ru/post/923042/


All Articles