I never thought it could be so simple.
However I should have clarified that it's a 1 character input. But the general idea is the same. Someone suggested that I explain what is going on better, so I'm going to do that. The function 'getch()' waits for a keyboard hit. But the reason that it has to be converted so many times in the line '(str(list(str(getch()))[2]))' is because getch() has to be annoying and add a b(It's a nonetype) before everything, and to be even more annoying, it's not a string (grrr)... So we have to first convert the whole thing to a string, put it in a list, take the 3rd item from the list, which would be the character you pressed. Convert it back to a string, then print it.

Edited 7 Years Ago by AutoPython: n/a

from msvcrt import getch

while True:
    print (str(list(str(getch()))[2]))

You should probably document your code to explain what each bit is doing, like why you need the third item in the list, why it need to be converted so many times, and what getch() and msvrt are.

But other then that, good snippet


Thanks for the feed back! I never thought about documenting it that much, but why not. It's a small snippet.

This is not that new. msvcrt.getch() was available on Windows with Python 2.5 already. Well, at least it was in the ActivePython distro. (Meaning: It's good news for pythoneers locked into older versions of Python.)

That said, a good example of a finer grained keyboard/console control compared to the more "traditional", "terminal"-oriented methods.

Edited 7 Years Ago by pythopian: n/a

I realized that it wasn't that new, but I just wanted to show everybody a simpler way of dong it, many versions of these are really long and clunky, and those aren't the ones I suggest you use. Especially the Tkinter ones. Blah, they stop working after you click the screen or anything else.

Interestingly though, I just checked how it works with Py 2.5 on my Windows box, and the snippet crashed. It is because, in my context, getch() always returns a 1-char string.

It might be that the getch() behaviour has changed between msvcrt versions - either that of the python module, or that of the underlying MS C++ library on the system. That's irritating though, because AFAICT the Python folks are damn careful about braking interfaces. :-/

In general, one ought to avoid platform specific code with a cross platform language like Python.

This code works only on Windows, the Tkinter approach may look mildly more complex, but it is cross platform.

Edited 5 Years Ago by vegaseat: windows

In general, one ought to avoid platform specific code with a cross platform language like Python.

While I personally do favor platform-independent code, I wouldn't agree with that statement on absolute terms. There is at least one situation when it's perfectly OK to have platform specific code: In platform-specific implementations of a generic interface. Example: Python's getpass() function uses msvcrt in its implementation on Windows.

I'd extend the principle to "Don't use platform specific code if there is a platform independent alternative. If there is none, encapsulate the platform-specific code behind a designated module interface."

Back to the topic at hand: Any clue why the snippet fails in one context, while it is (obviously) working in AutoPython's case? Anybody?

The reason Pythopian, is because in Python 2.5(and 2.6), getch() returns characters like 'a', 'e', '2', '(' etc. But in Python 3.1 it does b'a', b'3', b'5'. I was wondering if it was almost a bug.

The C function getch() will return a byte string in Python3, so you have to decode it.

Something like that ...

# windows console only
# C:\Windows\System32\msvcrt.dll contains C functions

from msvcrt import getch

while True:
    # Python3 byte string to string
    print( getch().decode("utf8") )
straight to the point.

Fro me the vegaseat's code does not function well, this version works from command line (not IDLE):

# windows console only
# C:\Windows\System32\msvcrt.dll contains C functions

from msvcrt import getch
mystring = c = ''
while c.lower() != 'q':
    c = getch().decode("cp437")
    mystring += c

print('Inputed string:', mystring)

This newer snippet of mine shows cross platform way with Tkinter:
Tkinter for console getkey, Pause/Restart/Quit

Edited 5 Years Ago by pyTony: n/a