3

I'm experiencing problems with the getch() function of the curses library. Suppose we have the following program:

import curses

def main(stdscr):
    while 1:
        c = stdscr.getch()
        stdscr.addstr(chr(c) + ": " + str(c) + "\n")
curses.wrapper(main)

Let's run this, and enter the following characters: a, <backspace>, œ

Then the output is:

a: 97
ć: 263
Å: 197

As you see, the a character is taken correctly. However, the others are not. I just want to get the backspace '\b' and the unicode character œ, but we get something else.

Why does getch() behave this way, and how can I get the desired behaviour?

EDIT:

Let me emphasize that's it's not an issue with printing the characters, but with reading the characters. Namely, running stdscr.addstr('œ') indeed prints œ.

chtenb
  • 14,924
  • 14
  • 78
  • 116

1 Answers1

4

In Python 3.3 the window.get_wch function was added. It handles all of those characters correctly.

If you read the documentation for window.getch, you'll notice that it doesn't claim to support non-ASCII printable characters. It just documents that it can handle non-ASCII key presses such as function keys or keypad keys.

EDIT:

When using window.get_wch, characters (e.g. 'a', 'ă', '好', '\n', or '\t') are returned as strings. Function keys are returned as integers (e.g. 265 or 274). Here is a new example to run. Try playing with the different keys you want to recognize to see how their values are returned. The format of the data printed is: [repr]: [type].

def main(stdscr):
    while 1:
        c = stdscr.get_wch()
        stdscr.addstr("%s: %s\n" % (repr(c), type(c)))

Here is what I get when I type in a, œ, <enter>, <backspace>, and <F1>:

'a': <class 'str'>
'œ': <class 'str'>
'\n': <class 'str'>
'\x7f': <class 'str'>
265: <class 'int'>

If an integer is returned, you can find out the name of the key pressed via curses.keyname:

>>> curses.keyname(265)
b'KEY_F(1)'
tsroten
  • 2,534
  • 1
  • 14
  • 17
  • This indeed works for the `œ`, but the `` (and ``, ``, ``,... etc) characters are still treated wrongly. – chtenb Mar 04 '14 at 15:54
  • I added information to the answer about return values. – tsroten Mar 04 '14 at 17:03
  • For me your script returns `'\n': `, `330: ` and `265: ` when typing ``, `` and ``. So the `` is still treated wrongly, while it works apparently for you. – chtenb Mar 04 '14 at 17:23
  • You got ``330`` when typing ````. ``curses.keyname(330)`` returns ``'KEY_DC'``. – tsroten Mar 05 '14 at 00:04
  • Backspace/Delete work differently on different computers. I'm running Mac OS X, where my "Backspace" (says "Delete" on it) returns ``'\x7f'`` -- the ASCII value for *Delete*. Your "Delete" key returned ``330``, which corresponds to the key name ``'KEY_DC'``. The ``KEY_DC`` constant [refers to the *delete character*](http://docs.python.org/3.3/library/curses.html#constants). What do you get when you press ````? – tsroten Mar 05 '14 at 00:10
  • It also depends on the terminal settings. [``curses.erasechar``](http://docs.python.org/3.3/library/curses.html#curses.erasechar) can be helpful here. ``erasechar`` returns ``b'\x7f'`` for me. – tsroten Mar 05 '14 at 00:20
  • Yes, indeed `curses.keyname` returns the right names for `` and ``. However, I expect (and need) to get `b'\x7f'` in the first place when pressing delete, instead of getting some other number. Similarly when pressing backspace, I need to have the `'\b'` character. – chtenb Mar 05 '14 at 10:44
  • For me `curses.erasechar()` returns `b'\x7f'` as well. – chtenb Mar 05 '14 at 10:45
  • First of all, I'm sorry that earlier I made a typo when I said that I pressed "delete" and got ``'\x7f'``. I should have said 'backspace'. Second of all, the ```` key does not and should not return ``'\x7f'``. ``'\x7f'`` is an ASCII character, not a key name. The delete key doesn't correspond to an ASCII character, so you *shouldn't* expect it to. You *should* expect it to return ``curses.KEY_DC``. Third of all, the way to handle backspace is not to expect ``'\b'`` (or ``'\x08'``), but to expect whatever is returned by ``curses.erasechar()``. I hope that helps clear things up. – tsroten Mar 05 '14 at 12:01
  • If you *must* have ``'\b'``, then yes, you'll need to handle that case manually. On some computers and terminals, ``'\b'`` may be returned by ````, that's why it's good to check ``curses.erasechar()``. The ```` key probably shouldn't be considered ``'\x7f'`` (see [Wikipedia on the delete *character*](http://en.wikipedia.org/wiki/Delete_character) -- not *key*), but you can handle it that way if you need to. – tsroten Mar 05 '14 at 13:45