By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,187 Members | 1,038 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,187 IT Pros & Developers. It's quick & easy.

Check for keypress on Linux xterm ?

P: n/a
Hello,

I'd like to check, if a single key is pressed on a Linux xterm.
This code waits for a key to be pressed and returns the character:

--------------------------------------------

#!/usr/bin/env python

import sys
import tty
import termios

fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)

def getOneKey():

try:
tty.setcbreak(sys.stdin.fileno())
ch = sys.stdin.read(1)
return ord(ch)

finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)

while True:
a = chr(getOneKey())
print a

--------------------------------------------

My problem is, I don't want my program to wait for the keypress.
I just want to check, if a key is currently pressed and if not, I'd like to
continue with my program (like "INKEY$" in some BASIC-dialects).

I tried several things:

- event-handling from pygame: But that would open a pygame-window, I don't
need.
- same thing for window-managers like Tkinter.
- threads: I couldn't do it (especially return values from thread-functions
to the main-program).
- curses: "nodelay()" or "halfdelay()" sound interesting. Maybe; but don't
know how right now. I even wouldn't be able to "print" then ...
- python-Xlib: Too complicated for me too right now; perhaps, if
documentation becomes more complete.

Does anybody know a code example (for Linux xterm) that does it ?

TIA

H.
Apr 9 '07 #1
Share this Question
Share on Google+
7 Replies


P: n/a
On 2007-04-09, hlubenow <hl*******@gmx.netwrote:
My problem is, I don't want my program to wait for the keypress.
I just want to check, if a key is currently pressed and if not, I'd like to
continue with my program (like "INKEY$" in some BASIC-dialects).
The answer to this frequently asked question is actually in the FAQ:

http://www.python.org/doc/faq/librar...ress-at-a-time

Google finds us further examples:

http://mail.python.org/pipermail/pyt...ry/010140.html
http://mail.python.org/pipermail/pyt...ne/041251.html

--
Grant Edwards grante Yow! I'm reporting for
at duty as a modern person. I
visi.com want to do the Latin
Hustle now!
Apr 10 '07 #2

P: n/a
Grant Edwards wrote:
On 2007-04-09, hlubenow <hl*******@gmx.netwrote:
>My problem is, I don't want my program to wait for the keypress.
I just want to check, if a key is currently pressed and if not, I'd like
to continue with my program (like "INKEY$" in some BASIC-dialects).

The answer to this frequently asked question is actually in the FAQ:

http://www.python.org/doc/faq/librar...ress-at-a-time
>
Google finds us further examples:

http://mail.python.org/pipermail/pyt...ry/010140.html
http://mail.python.org/pipermail/pyt...ne/041251.html
You're answer is only less than half correct:

Most of the given examples use something like

c = sys.stdin.read(1)

like my example does. This blocks input. At the end of your last link the
author there says it. He also shows some ways into my direction.
I'll test them.

H.
Apr 10 '07 #3

P: n/a
Grant Edwards wrote:
On 2007-04-09, hlubenow <hl*******@gmx.netwrote:
>My problem is, I don't want my program to wait for the keypress.
I just want to check, if a key is currently pressed and if not, I'd like
to continue with my program (like "INKEY$" in some BASIC-dialects).

The answer to this frequently asked question is actually in the FAQ:

http://www.python.org/doc/faq/librar...ress-at-a-time
>
Google finds us further examples:

http://mail.python.org/pipermail/pyt...ry/010140.html
http://mail.python.org/pipermail/pyt...ne/041251.html
I see now, you're right. Sorry.
Apr 10 '07 #4

P: n/a
On 2007-04-10, hlubenow <hl*******@gmx.netwrote:
>>My problem is, I don't want my program to wait for the
keypress. I just want to check, if a key is currently pressed
and if not, I'd like to continue with my program (like
"INKEY$" in some BASIC-dialects).

The answer to this frequently asked question is actually in the FAQ:

http://www.python.org/doc/faq/librar...ress-at-a-time

You're answer is only less than half correct:

Most of the given examples use something like

c = sys.stdin.read(1)

like my example does. This blocks input.
read() will not block if the file has been set to non-blocking
mode. That's what these two lines in the FAQ answer do:

oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)

I do make mistakes, but before telling somebody he's wrong, it
might be a good idea to actually try what he's suggested. ;)

--
Grant Edwards grante Yow! Edwin Meese made me
at wear CORDOVANS!!
visi.com
Apr 10 '07 #5

P: n/a
Grant Edwards wrote:
I do make mistakes, but before telling somebody he's wrong, it
might be a good idea to actually try what he's suggested. ;)
I completely agree. The script waited at first for key-input, so I thought,
I was right. But I was not. I apologize !

H.
Apr 10 '07 #6

P: n/a
I wrote:
Hello,

I'd like to check, if a single key is pressed on a Linux xterm.
My problem is, I don't want my program to wait for the keypress.
I just want to check, if a key is currently pressed and if not, I'd like
to continue with my program (like "INKEY$" in some BASIC-dialects).
Ok, here's the code I use now. Thanks to Grant Edwards for pointing me into
the right direction:

----------------------------------------------------------

#!/usr/bin/env python

import os
import sys
import tty
import termios
import fcntl
import time

fd = sys.stdin.fileno()

oldterm = termios.tcgetattr(fd)
oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)

tty.setcbreak(sys.stdin.fileno())
newattr = termios.tcgetattr(fd)
newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
def oldTerminalSettings():
termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)
def newTerminalSettings():
termios.tcsetattr(fd, termios.TCSANOW, newattr)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)
def checkKey():

try:
c = sys.stdin.read(1)
return ord(c)

except IOError:
return 0

print
print "Ok, in 3 seconds, I'll check 100 times, which key you press."
print

# Initializing: Things like "raw_input()" won't work after that:
newTerminalSettings()

time.sleep(3)

for i in range(100):
a = "Key pressed: "

key = checkKey()

if key:
a += chr(key)
a += "."
else:
a += "Nothing pressed."

print a

# Somehow it doesn't work, if this loop runs too fast, so:
time.sleep(0.05)

oldTerminalSettings()

print
print "Terminal-settings restored."
print
raw_input("raw_input() works again. So please press Return: ")
print

----------------------------------------------------------

Thanks again

H.
Apr 11 '07 #7

P: n/a
On 2007-04-11, hlubenow <hl*******@gmx.netwrote:
I wrote:
>Hello,

I'd like to check, if a single key is pressed on a Linux xterm.
My problem is, I don't want my program to wait for the keypress.
I just want to check, if a key is currently pressed and if not, I'd like
to continue with my program (like "INKEY$" in some BASIC-dialects).

Ok, here's the code I use now. Thanks to Grant Edwards for pointing me into
the right direction:

----------------------------------------------------------

#!/usr/bin/env python

import os
import sys
import tty
import termios
import fcntl
import time

fd = sys.stdin.fileno()

oldterm = termios.tcgetattr(fd)
oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)

tty.setcbreak(sys.stdin.fileno())
newattr = termios.tcgetattr(fd)
newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
def oldTerminalSettings():
termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)
def newTerminalSettings():
termios.tcsetattr(fd, termios.TCSANOW, newattr)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)
def checkKey():

try:
c = sys.stdin.read(1)
return ord(c)

except IOError:
return 0
Ah, but how do you tell "no key" from ctrl-@ (which has a
ordinal value of 0)? If I were you, I'd return None in the case
where there is nothing to return:

def checkKey():
try:
return ord(sys.stdin.read(1))
except IOError:
return None

I'm also not sure if there are other possible causes for the
IOError exception that you'd need to watch out for. Ideally,
you'd check to make sure its an EAGAIN.
print
print "Ok, in 3 seconds, I'll check 100 times, which key you press."
print

# Initializing: Things like "raw_input()" won't work after that:
newTerminalSettings()

time.sleep(3)

for i in range(100):
a = "Key pressed: "

key = checkKey()

if key:
And here, you'd have this:

if key is not None:
a += chr(key)
a += "."
else:
a += "Nothing pressed."

print a

--
Grant Edwards grante Yow! When you get your
at PH.D. will you get able to
visi.com work at BURGER KING?
Apr 11 '07 #8

This discussion thread is closed

Replies have been disabled for this discussion.