19

In the Python curses module, I have observed that there is a roughly 1-second delay between pressing the esc key and getch() returning. This delay does not seem to occur for other keys. Why does this happen and what can I do about it?

Test case:

import curses
import time

def get_delay(window, key):
    while True:
        start = time.time()
        ch = window.getch()
        end = time.time()
        if ch == key:
            return end-start

def main(stdscr):
    stdscr.clear()
    stdscr.nodelay(1)

    stdscr.addstr("Press ESC")
    esc_delay = get_delay(stdscr, 27)

    stdscr.addstr("\nPress SPACE")
    space_delay = get_delay(stdscr, ord(' '))

    return esc_delay, space_delay

if __name__ == '__main__':
    esc_delay, space_delay = curses.wrapper(main)
    print("Escape delay: {} ms".format(esc_delay*1000))
    print("Space delay: {} ms".format(space_delay*1000))

Results:

Escape delay: 1001.09195709 ms
Space delay: 0.00596046447754 ms
augurar
  • 12,081
  • 6
  • 50
  • 65

4 Answers4

25

In order to customize the Esc delay you can set the environment variable ESCDELAY which curses uses to determine the time in milliseconds it waits before it delivers the Escape Key.

In order to define this variable in Python you could for example call the following function prior to your call to curses.wrapper(main):

def set_shorter_esc_delay_in_os():
    os.environ.setdefault('ESCDELAY', '25')

which will set the environment variable to 25ms if it has not been set before.

See also the man page of ncurses (search for ESCDELAY).

Salo
  • 1,936
  • 15
  • 24
  • Mmh ok, don't have OS X, but according this [man page](https://developer.apple.com/library/ios/documentation/System/Conceptual/ManPages_iPhoneOS/man3/ncurses.3x.html), ncurses should be aware of the ESCDELAY environment variable.. – Salo Feb 27 '15 at 12:42
  • 3
    This works but it has to be called before initializing curses. – MCSH Jul 01 '16 at 01:38
  • 3
    In C, there are two functions named `set_escdelay` and `get_escdelay`. When using these functions, the delay is measured in milliseconds. – ManuelAtWork Aug 04 '16 at 10:10
  • @ManuelAtWork They also added these functions into python in python 3.9. See my answer below. – charlescochran Jul 20 '23 at 16:15
4

Curses deals with "escape sequence"s from your terminal to represent commands to the software These sequences normally begin with an escape character. Consequently, when you hit ESC the curses code doesn't emit anything immediately in case this represents the start of an escape sequence.

holdenweb
  • 33,305
  • 7
  • 57
  • 77
1

To anyone still looking, Python 3.9 added curses.get_escdelay() and curses.set_escdelay(ms) for controlling the delay after ESC is pressed. Units are milliseconds. See the docs.

For example, calling

curses.set_escdelay(25)

will set the delay to 25 milliseconds.

Now that this is available, I think it is cleaner than the accepted method:

os.environ.setdefault('ESCDELAY', '25')
-2

ESCDELAY=25 ...put this in global.

linux
  • 5
  • 1