Keyboard Input
Python’s built-in input() function is great for simple prompts, but it has
one limitation: it waits for the Enter key. This makes it unsuitable for
interactive applications that need to respond to individual keystrokes, arrow
keys, or function keys.
Blessed provides a solution with inkey(), which returns
keystrokes as they are pressed, as Keystroke objects.
Overview
The cbreak() context manager enables immediate key detection.
The inkey() method returns a Keystroke object
representing the key that was immediately pressed.
Getting Started
Here’s a simple example that reads a single keystroke:
1#!/usr/bin/env python3
2from blessed import Terminal
3
4term = Terminal()
5with term.cbreak():
6 key = term.inkey()
7 print(f"You pressed: {key!r}")
The inkey() method also accepts a timeout parameter that
defaults to 1 second. When timeout is exceeded without input, an empty
Keystroke is returned, ''.
In this example, a 10Hz animation is displayed by timeout=0.1, stopped
by pressing any key:
1#!/usr/bin/env python3
2from blessed import Terminal
3
4term = Terminal()
5print("Cross animation, press any key to stop: ", end="", flush=True)
6with term.cbreak(), term.hidden_cursor():
7 cross = '|'
8
9 while True:
10 key = term.inkey(timeout=0.1)
11 if key:
12 print(f'STOP by {key!r}')
13 break
14
15 cross = {'|': '-', '-': '|'}[cross]
16 print(f'{cross}\b', end='', flush=True)
Keystroke
The Keystroke class makes it easy to work with keyboard input. It
inherits from str, so you can compare it directly to other strings, but
it also provides special properties for detecting modifier keys and special
sequences.
Use
is_sequenceto detect special keysUse
nameto identify special keys by name (e.g.,KEY_F1,KEY_CTRL_Q)Or, by using magic methods like
keystroke.is_f1()orkeystroke.is_key_ctrl('q').
Be careful printing Keystroke objects directly. Our examples uses
format string, f'{ks!r}' for repr(), because str(ks) may contain
control characters or escape sequences beginning with (KEY_ESCAPE) and are
generally unprintable.
Special Keys
The is_sequence property returns True for arrow keys,
function keys, and any character key combined with modifiers (Ctrl, Alt, Shift).
1#!/usr/bin/env python3
2from blessed import Terminal
3
4term = Terminal()
5with term.cbreak():
6 key = term.inkey()
7
8 if key.is_sequence:
9 print(f"Special key: {key.name} ({key!r})")
10 else:
11 print(f"Regular character: {key}")
The str(key) value for Keystroke should not be directly printed
when is_sequence is True as done in this and other examples.
The name property provides a readable name for special keys,
and can be used for basic equality tests, like in this “paint by arrow key” example:
1#!/usr/bin/env python3
2from blessed import Terminal
3
4header_msg = "Press arrow keys (or 'q' to quit): "
5term = Terminal()
6position = [term.height // 2, term.width // 2]
7with term.cbreak(), term.fullscreen(), term.hidden_cursor():
8 print(term.home + header_msg + term.clear_eos)
9
10 while True:
11 # show arrow-controlled block
12 print(term.move_yx(*position) + '█', end='', flush=True)
13
14 # get key,
15 key = term.inkey()
16
17 # take action,
18 if key == 'q':
19 break
20 if key.name == 'KEY_UP':
21 position[0] = max(0, position[0] - 1)
22 elif key.name == 'KEY_LEFT':
23 position[1] = max(0, position[1] - 1)
24 elif key.name == 'KEY_DOWN':
25 position[0] = min(term.height, position[0] + 1)
26 elif key.name == 'KEY_RIGHT':
27 position[1] = min(term.width, position[1] + 1)
Common key names include:
KEY_UP,KEY_DOWN,KEY_LEFT,KEY_RIGHT- Arrow keysKEY_ENTER- Enter/Return keyKEY_BACKSPACE,KEY_DELETE- Backspace and Delete keysKEY_TAB- Tab keyKEY_ESCAPE- Escape keyKEY_F1throughKEY_F12- Function keysKEY_PGUP,KEY_PGDOWN- Page Up and Page DownKEY_HOME,KEY_END- Home and End keys
For regular characters without modifiers, name returns
None in legacy mode. In Kitty keyboard protocol
mode, all ASCII alphanumeric and punctuation keys receive synthesized names
– see Key Name Synthesis.
Feel free to try the demonstration program, keymatrix.py to experiment with possible keyboard inputs and combinations.
Modifiers
Alphanumeric keys with modifiers follow the pattern:
KEY_CTRL_AKEY_ALT_QKEY_CTRL_ALT_Y
For alphanumeric keys, SHIFT is not represented in the key name.
Instead, case is handled through the character itself and the ignore_case
parameter in Magic Methods. Control characters are case-insensitive at the
protocol level (Ctrl+A and Ctrl+Shift+A are identical). For Alt
modifiers, use ignore_case=False to distinguish case: key.is_alt('a',
ignore_case=False) matches only lowercase, while key.is_alt('A',
ignore_case=False) matches only uppercase.
Application keys (arrows, function keys, etc.) support SHIFT in their names:
KEY_SHIFT_LEFTKEY_CTRL_ALT_BACKSPACEKEY_ALT_DELETEKEY_CTRL_SHIFT_F3KEY_CTRL_ALT_SHIFT_F9
When multiple modifiers are specified in application key names, they are always in the following order:
CTRLALTSHIFT
The escape sequence '\x1b[' is always decoded as name CSI in legacy
mode when it arrives without any known matching sequence.
The value property returns the text character for keys that
produce text, stripping away modifier information.
Special keys like KEY_UP, KEY_F1, KEY_BACKSPACE
have an empty value string.
Control characters like KEY_CTRL_C are value c
(lowercase). Similarly for alt, KEY_ALT_a is value
a.
Event Types
The Keystroke class provides properties about key events:
pressed-Trueif this is a key press eventrepeated-Trueif this is a key repeat eventreleased-Trueif this is a key release event
For press/release tracking, two additional properties provide stable identifiers across event types:
key_name- likename, but without the_RELEASEDor_REPEATEDsuffix, so that the same key always returns the same name regardless of event type.key_value- likevalue, but returns the character even for release events (wherevaluereturns'').
Note: These event types can only be distinguished when using the Kitty
Keyboard Protocol. Without it, all keystrokes will have
pressed=True and repeated=False, released=False.
See Kitty Keyboard Protocol for more information about enabling and using the Kitty Keyboard Protocol.
Magic Methods
The Keystroke class provides convenient “magic methods” for checking
keys with modifiers. These methods all start with is_:
1#!/usr/bin/env python3
2from blessed import Terminal
3
4term = Terminal()
5print("Press 'q' or F10 to exit! Press F1 for help")
6with term.cbreak():
7 while True:
8 key = term.inkey()
9
10 # Check for specific character with modifier
11 if key.is_ctrl('q') or key.is_f10():
12 print(f"Exit by key named {key.name}")
13 break
14
15 # Check for function key
16 elif key.is_f1():
17 print("* don't panic")
Some examples, given key object of Keystroke:
key.is_ctrl('x')key.is_alt('q')key.is_ctrl_alt('s')key.is_ctrl_shift_alt('a')key.is_f1()key.is_up()key.is_enter()key.is_backspace()key.is_ctrl_left()key.is_alt_backspace()key.is_shift_f5()
By default, character matching is case-insensitive. You can change this with the
ignore_case parameter. For example, “Alt” with capital letter U matches
both methods:
key.is_alt('u')key.is_alt_shift('u')
To explicitly match only “Alt + u” (lowercase ‘U’), set ignore_case
argument to False:
key.is_alt('u', ignore_case=False)
All Names
These are duplicated from the key names found in curses(3), or those
constants in
curses beginning with phrase KEY_, as follows:
All Terminal class attribute Keyboard codes, by name Name
Value
Example Sequence(s)
KEY_BACKSPACE
263
‘\x08’, ‘\x7f’
KEY_BEGIN
354
KEY_BTAB
353
KEY_CANCEL
355
KEY_CAPS_LOCK
57358
KEY_CATAB
342
KEY_CENTER
350
‘\x1b[E’
KEY_CLEAR
333
KEY_CLOSE
356
KEY_COMMAND
357
KEY_COPY
358
KEY_CREATE
359
KEY_CTAB
341
KEY_DELETE
330
‘\x1b[3~’
KEY_DL
328
KEY_DOWN
258
‘\x1b[B’, ‘\x1b[OB’
KEY_DOWN_LEFT
351
KEY_DOWN_RIGHT
352
KEY_EIC
332
KEY_END
360
‘\x1b[F’, ‘\x1b[K’, ‘\x1b[4~’, ‘\x1b[8~’, ‘\x1b[OF’
KEY_ENTER
343
‘\n’, ‘\r’, ‘\x1bOM’
KEY_EOL
335
KEY_EOS
334
KEY_ESCAPE
361
‘\x1b’
KEY_F0
264
KEY_F1
265
‘\x1bOP’, ‘\x1b[P’
KEY_F10
274
KEY_F11
275
KEY_F12
276
KEY_F13
57376
KEY_F14
57377
KEY_F15
57378
KEY_F16
57379
KEY_F17
57380
KEY_F18
57381
KEY_F19
57382
KEY_F2
266
‘\x1bOQ’, ‘\x1b[Q’
KEY_F20
57383
KEY_F21
57384
KEY_F22
57385
KEY_F23
57386
KEY_F3
267
‘\x1bOR’, ‘\x1b[13~’
KEY_F4
268
‘\x1bOS’, ‘\x1b[S’
KEY_F5
269
KEY_F6
270
KEY_F7
271
KEY_F8
272
KEY_F9
273
KEY_FIND
362
KEY_HELP
363
KEY_HOME
262
‘\x1b[H’, ‘\x1b[1~’, ‘\x1b[7~’, ‘\x1b[OH’
KEY_IL
329
KEY_INSERT
331
‘\x1b[2~’
KEY_ISO_LEVEL3_SHIFT
57453
KEY_ISO_LEVEL5_SHIFT
57454
KEY_KP_0
520
‘\x1bOp’
KEY_KP_1
521
‘\x1bOq’
KEY_KP_2
522
‘\x1bOr’
KEY_KP_3
523
‘\x1bOs’
KEY_KP_4
524
‘\x1bOt’
KEY_KP_5
525
‘\x1bOu’
KEY_KP_6
526
‘\x1bOv’
KEY_KP_7
527
‘\x1bOw’
KEY_KP_8
528
‘\x1bOx’
KEY_KP_9
529
‘\x1bOy’
KEY_KP_ADD
514
‘\x1bOk’
KEY_KP_BEGIN
57427
KEY_KP_DECIMAL
517
‘\x1bOn’
KEY_KP_DELETE
57426
KEY_KP_DIVIDE
518
‘\x1bOo’
KEY_KP_DOWN
57420
KEY_KP_END
57424
KEY_KP_ENTER
57414
KEY_KP_EQUAL
519
‘\x1bOX’
KEY_KP_HOME
57423
KEY_KP_INSERT
57425
KEY_KP_LEFT
57417
KEY_KP_MULTIPLY
513
‘\x1bOj’
KEY_KP_PAGE_DOWN
57422
KEY_KP_PAGE_UP
57421
KEY_KP_RIGHT
57418
KEY_KP_SEPARATOR
515
‘\x1bOl’
KEY_KP_SUBTRACT
516
‘\x1bOm’
KEY_KP_UP
57419
KEY_LEFT
260
‘\x1b[D’, ‘\x1b[OD’
KEY_LEFT_ALT
57443
KEY_LEFT_CONTROL
57442
KEY_LEFT_HYPER
57445
KEY_LEFT_META
57446
KEY_LEFT_SHIFT
57441
KEY_LEFT_SUPER
57444
KEY_LL
347
KEY_LOWER_VOLUME
57438
KEY_MARK
364
KEY_MAX
511
KEY_MEDIA_FAST_FORWARD
57433
KEY_MEDIA_PAUSE
57429
KEY_MEDIA_PLAY
57428
KEY_MEDIA_PLAY_PAUSE
57430
KEY_MEDIA_RECORD
57437
KEY_MEDIA_REVERSE
57431
KEY_MEDIA_REWIND
57434
KEY_MEDIA_STOP
57432
KEY_MEDIA_TRACK_NEXT
57435
KEY_MEDIA_TRACK_PREVIOUS
57436
KEY_MENU
57363
KEY_MESSAGE
365
KEY_MIN
257
KEY_MOUSE
409
KEY_MOVE
366
KEY_MUTE_VOLUME
57440
KEY_NEXT
367
KEY_NUM_LOCK
57360
KEY_OPEN
368
KEY_OPTIONS
369
KEY_PAUSE
57362
KEY_PGDOWN
338
‘\x1b[U’, ‘\x1b[6~’
KEY_PGUP
339
‘\x1b[V’, ‘\x1b[5~’
KEY_PREVIOUS
370
KEY_PRINT
346
KEY_PRINT_SCREEN
57361
KEY_RAISE_VOLUME
57439
KEY_REDO
371
KEY_REFERENCE
372
KEY_REFRESH
373
KEY_REPLACE
374
KEY_RESET
345
KEY_RESIZE
410
KEY_RESTART
375
KEY_RESUME
376
KEY_RIGHT
261
‘\x1b[C’, ‘\x1b[OC’
KEY_RIGHT_ALT
57449
KEY_RIGHT_CONTROL
57448
KEY_RIGHT_HYPER
57451
KEY_RIGHT_META
57452
KEY_RIGHT_SHIFT
57447
KEY_RIGHT_SUPER
57450
KEY_SAVE
377
KEY_SBEG
378
KEY_SCANCEL
379
KEY_SCOMMAND
380
KEY_SCOPY
381
KEY_SCREATE
382
KEY_SCROLL_LOCK
57359
KEY_SDC
383
KEY_SDL
384
KEY_SDOWN
336
‘\x1b[1;2B’
KEY_SELECT
385
KEY_SEND
386
KEY_SEOL
387
KEY_SEXIT
388
KEY_SFIND
389
KEY_SHELP
390
KEY_SHOME
391
KEY_SIC
392
KEY_SLEFT
393
‘\x1b[1;2D’
KEY_SMESSAGE
394
KEY_SMOVE
395
KEY_SNEXT
396
KEY_SOPTIONS
397
KEY_SPREVIOUS
398
KEY_SPRINT
399
KEY_SREDO
400
KEY_SREPLACE
401
KEY_SRESET
344
KEY_SRIGHT
402
‘\x1b[1;2C’
KEY_SRSUME
403
KEY_SSAVE
404
KEY_SSUSPEND
405
KEY_STAB
340
KEY_SUNDO
406
KEY_SUP
337
‘\x1b[1;2A’
KEY_SUSPEND
407
KEY_TAB
512
‘\t’
KEY_UNDO
408
KEY_UP
259
‘\x1b[A’, ‘\x1b[OA’
KEY_UP_LEFT
348
KEY_UP_RIGHT
349
However, these keys do not represent the full range of keys that can be detected
with their modifiers, such as KEY_CTRL_LEFT is not matched by any Keycode
constant, but rather a combination of existing KEY_LEFT with the CTRL
modifier.
For Legacy API of classic curses applications, code may be
be compared with attributes of Terminal, which are duplicated from
those found in curses(3), or those constants in curses
beginning with phrase KEY_. These have numeric values that can be used for
all basic application keys.
Async Input
The async_inkey() method is an asyncio-compatible version of
inkey(). It yields control to the event loop while waiting for
input, making it suitable for use with async/await.
import asyncio
from blessed import Terminal
async def main():
term = Terminal()
with term.cbreak():
key = await term.async_inkey(timeout=5.0)
if key:
print(f"You pressed: {key!r}")
else:
print("Timed out")
asyncio.run(main())
The method accepts the same timeout and esc_delay parameters as
inkey(). It must be called within a cbreak()
or raw() context.
For a complete example using async_inkey with the Line Editor, see
Line Editor.