How do I check if a key is being pressed during execution of a script so that I can halt execution if a key is pressed ?
I know that there’s CTRL-C, but this doesn’t work when a tight loop is being executed, so I need to check the keyboard explicitly.
I don’t think you can do that. The only Python keyboard input function that I know of is raw_input(), but it expect a line termination character before going further, so it would just stall the loop.
Martin
If you don’t mind using external libaries you can use pygame.
asdf_46
In that case, can I detect a mouse click instead ?
Or, can I explicitly tell python to yield execution of the current thread for a bit to allow whatever thread is responsible for detecting CTRL-C to get a chance to detect it ?
What do you mean by a ‘tight loop’? As far as I know, unless you disable it Ctrl-C is always detected. You can catch the Ctrl-C interrupt though, I did this in the LF script by using the signal module, here is a simple example:
import signal, random
CTRL_C_USED = 0
def handler(signum, frame):
global CTRL_C_USED
# reset sighandler to default after first break
signal.signal(signal.SIGINT, signal.default_int_handler)
CTRL_C_USED = 1
signal.signal(signal.SIGINT, handler)
while not CTRL_C_USED: print "Stop me!", random.randint(1, 10000)
print "Ok, thanks!"
This will loop continuously until you press Ctrl-C and just continues without interrupting the script. It is one time use only, meaning as soon as you use Ctrl-C, the signal handler is reset to default, but you can change that of course if needed, although it is probably best to at least reset it when the script ends.
For other ways to deal with keyboard events look at the msvcrt module on windows, or possibly the select module for other platforms, both are also used in the LF script.
The disadvantage of all of these though is they all rely on the console.
Hi,
To get a keypress without blocking is dependent on the platform. If you want to make something cross platform, you can check like this:
import sys
if sys.platform=='win32':
...
else:
...
The following information is from the Python FAQ and assumes you have the full Pyton installation:
Windows
Use the msvcrt module. This is a standard Windows-specific extensions in Python 1.5 and beyond. It defines a function kbhit() which checks whether a keyboard hit is present; also getch() which gets one character without echo. Plus a few other goodies.
Linux
There are several solutions; some involve using curses, which is a pretty big thing to learn. Here’s a solution without curses.
import termios, fcntl, sys, os
fd = sys.stdin.fileno()
oldterm = termios.tcgetattr(fd)
newattr = termios.tcgetattr(fd)
newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
termios.tcsetattr(fd, termios.TCSANOW, newattr)
oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)
try:
while 1:
try:
c = sys.stdin.read(1)
print "Got character", `c`
except IOError: pass
finally:
termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)
You need the termios and the fcntl module for any of this to work, and I’ve only tried it on Linux, though it should work elsewhere.
In this code, characters are read and printed one at a time.
termios.tcsetattr() turns off stdin’s echoing and disables canonical mode. fcntl.fnctl() is used to obtain stdin’s file descriptor flags and modify them for non-blocking mode. Since reading stdin when it is empty results in an IOError, this error is caught and ignored.
Good luck,
Stani
http://spe.pycs.net (python editor for blender)
http://www.stani.be