I'm attempting to write a simple programme that displays the current status of the different keylocks, but I'm unable to find a solution as to how to get the current status of them in Python. Thank you.
-
Sorry, should have mentioned. Linux. – Oct 29 '12 at 21:24
-
1You could use [`python-keyboardleds`](http://jwilk.net/software/python-keyboardleds) (Linux only) – Lukas Graf Oct 29 '12 at 21:33
-
@LukasGraf Thanks, but I think I'll go with the other option, as that doesn't require me to pull in any outside packages. Either way though, thanks! – Oct 29 '12 at 21:42
-
@DoDoGo Good choice :) If you want to eliminate the dependency on `xset` and a shell call as well, you could do it all yourself from Python by doing the right ioctls on `/dev/console`. Figuring out how to from looking at python-keyboardleds' source should be trivial (reading from `/dev/console` will unfortunately require root privileges though). – Lukas Graf Oct 29 '12 at 21:51
-
I'll try doing that as an exercise, but I'm intending for this to run in userspace. Thanks for the suggestion though, as this gives me something to try out over the weekend. Anything will help since I only recently started with Python. – Oct 29 '12 at 21:59
-
@DoDoGo The thing is, this is much more related to Linux that to Python. But since you seem to have some solid Linux knowledge, you might want to add `man console_ioctl` to your weekend reading-list ;-) – Lukas Graf Oct 29 '12 at 22:19
-
@LukasGraf I definitely will, as it appears it's something I have absolutely no knowledge of currently. Thank you for your pointers, as this gives me a nice direction to go in to learn more! – Oct 29 '12 at 22:37
8 Answers
If you can wait a day or two, I'll add this functionality to python-evdev and update this answer. It's probably going to look something along the lines of:
from evdev import InputDevice, ecodes
dev = InputDevice('/dev/input/eventX') # your keyboard device
dev.ledstates(verbose=True)
{ (0, 'LED_NUML') : True,
(1, 'LED_CAPSL') : True,
(2, 'LED_SCROLLL') : False}
Using xset
, as mentioned by @ronak, is a lot easier since you don't have to have read permissions on any input devices. Unfortunately, it works only under X (and X in turn uses the evdev
interface (at least on linux)).
Well, It took me long enough, but it's in. The interface for getting 'ON' LEDs ended up being:
>>> dev.leds()
[0, 1, 8, 9]
>>> dev.leds(verbose=True)
[('LED_NUML', 0), ('LED_CAPSL', 1), ('LED_MISC', 8), ('LED_MAIL', 9)]
Getting all available LEDs on a device:
>>> dev.capabilities()[ecodes.EV_LED]
[0, 1, 2]
>>> dev.capabilities(verbose=True)[('EV_LED', ecodes.EV_LED)]
[('LED_NUML', 0), ('LED_CAPSL', 1), ('LED_SCROLLL', 2)]

- 3,977
- 30
- 31
-
1This looks great! If you don't mind adding that, I love this solution (and the fact that it solves the problem long term)! – Oct 29 '12 at 21:54
-
1Thank you for implementing this, @gvalkov. In today's implementation, it seems that one must use `dev.leds()` to get a `list` of active LEDs, each being an `int`. – mszegedy Apr 16 '15 at 23:04
Ok, after reading the source code for python-keyboardleds
and the console_ioctl
manpage, here's how to do it in plain Python:
import os
import struct
import fcntl
DEVICE = '/dev/tty'
_KDGETLED = 0x4B31
scroll_lock = 0x01
num_lock = 0x02
caps_lock = 0x04
fd = os.open(DEVICE, os.O_WRONLY)
# ioctl to get state of leds
bytes = struct.pack('I', 0)
bytes = fcntl.ioctl(fd, _KDGETLED, bytes)
[leds_state] = struct.unpack('I', bytes)
# Use bitmask to check status caps_lock bit
status = leds_state & caps_lock != 0
print "Caps Lock is On: %s" % status
Note: This only works for real terminals and VTs (1-7, those accessible with ctrl+alt+Fx), not for pseudo-terminals in an X11 terminal emulator for example.
To check, run tty
in your console:
$ tty
/dev/tty1 # will work
$ tty
/dev/pts/4 # won't work
Using /dev/console
as the device to query will work in X11 as well, but requires root privileges.
For details on the concepts involved see the Wikipedia pages on ioctls and bitmasking, and the docs to the Python fcntl
module.

- 30,317
- 8
- 77
- 92
-
Thanks, while I won't be using this, I appreciate the example on ioctls. I'll definitely go over this on the weekend! – Oct 30 '12 at 19:47
└──> xset q | grep LED
auto repeat: off key click percent: 0 LED mask: 00000000
└──> xset q | grep LED
auto repeat: off key click percent: 0 LED mask: 00000001
When the caps lock is on, the LED mask should be 1 and if the LED mask is off, it should be 0.
Additionally since you mentioned that you wanted to use python, you could get the value in the following way
>>> import commands
>>> # Caps Lock is off.
>>> commands.getoutput('xset q | grep LED')[65]
'0'
>>> # Setting Caps Lock on now.
>>> commands.getoutput('xset q | grep LED')[65]
'1'
python 3 version:
import subprocess
if subprocess.check_output('xset q | grep LED', shell=True)[65] == 50 :
capslock = False
if subprocess.check_output('xset q | grep LED', shell=True)[65] == 51 :
capslock = True
print( "capslock ON is : ", capslock )

- 1,248
- 14
- 19

- 1,770
- 3
- 20
- 34
-
1Thanks! I see that 0 is none, 1 is capslock, 2 is numlock, 4 scroll lock and afterwards it adds up. Great! – Oct 29 '12 at 21:39
-
6From the docs, `Deprecated since version 2.6: The commands module has been removed in Python 3. Use the subprocess module instead.` – Aug 28 '13 at 14:49
-
1There are cases where the keyboard LED does not accurately represent the state of caps lock. – tweej Sep 21 '15 at 17:05
for checking caps lock you can use this:
import ctypes
def is_capslock_on():
return True if ctypes.WinDLL("User32.dll").GetKeyState(0x14) else False
print(is_capslock_on())

- 198
- 1
- 2
- 18
Also see tkinter - that has events for Caps-Lock. I used xset to find the initial status of Caps-Lock when I open a panel, and then used the tkinter event to keep track whilst the panel is open. 1) I was not sure how to get the initial state in tkinter - there must be a way 2 xset did not seem reliable within the tkinter event proc - the proc did not always show the caps-lock change via xset...
Sample code:
def capsLock(event):
caps = event.state & 0x0002
To expand on the answer provided by ronak, the python3 version works the way it should but only when num lock is turned on.
subprocess.check_output('xset q | grep LED', shell=True)[65]
returns the values 48 through 51, depending on the status of numlock and caps lock (capslock adds a value of 1, whereas numlock adds 2)
This should work taking numlock into consideration:
import subprocess
x=subprocess.check_output('xset q | grep LED', shell=True)[65]
if x==48 or x==50:
print("caps off")
if x == 48:
print("num off")
else:
print("num on")
elif x==49 or x==51:
print("caps on")
if x == 49:
print("num off")
else:
print("num on")```
if your OS is Windows, try:
import win32api,win32con
caps_status = win32api.GetKeyState(win32con.VK_CAPITAL)
if caps_status==0:
print('CapsLock is off')
else:
print('CapsLock is on')

- 107
- 3
Look at https://stackoverflow.com/a/21160382/10871895 for caps lock key under Windows without loading additional modules.

- 87
- 6