[Pythonmac-SIG] Non blocking terminal input
Samuel M. Smith
smithsm at samuelsmith.org
Fri Feb 6 13:39:14 EST 2004
Thanks Bob for the clue of where to look.
Actually it took some digging to make it work. The python termios
doesn't have the O_NONBLOCK flag it is in os.open(). In unix both
fcntl and open support O_NONBLOCK but only python os.open() exports it.
This kind of threw me because I didn't want to open the console I just
wanted to change is state so os.fcntl was what I wanted but it didn't
support. I tried os.open anyway and reopened the console. This seemed
problematic but I guess you can open the same file multiple times with
different file descriptors. The only problem I had was mixing print to
stdout and writes to the new nonblocking fd = 3. Newlines were getting
mixed up.
Anyway I thought others might be interested. Here is a short class that
supports nonblocking reads from the console.
class ConsoleNB(object):
"""Class to manage non blocking reads from console.
Opens non blocking read file descriptor on console
Use instance method close to close file descriptor
Use instance methods getline & put to read & write to console
Needs os module
"""
def __init__(self, canonical = True):
"""Initialization method for instance.
opens fd on terminal console in non blocking mode
os.ctermid() returns path name of console usually '/dev/tty'
os.O_NONBLOCK makes non blocking io
os.O_RDWR allows both read and write.
Don't use print as same time since it could mess up non
blocking reads.
Default is canonical mode so no characters available until
newline
"""
#need to add code to enable non canonical mode
self.fd = os.open(os.ctermid(),os.O_NONBLOCK | os.O_RDWR)
def close(self):
"""Closes fd. Should use in try finally block.
"""
os.close(self.fd)
def getline(self,bs = 80):
"""Gets nonblocking line from console up to bs characters
including newline.
Returns None if no characters available else returns line.
In canonical mode no chars available until newline is entered.
"""
line = None
try:
line = os.read(self.fd, bs)
except OSError, ex1: #if no chars available generates exception
try: #need to catch correct exception
errno = ex1.args[0] #if args not sequence get TypeError
if errno == 35:
pass #No characters available
else:
raise #re raise exception ex1
except TypeError, ex2: #catch args[0] mismatch above
raise ex1 #ignore TypeError, re-raise exception ex1
return line
def put(self, data = '\n'):
"""Writes data string to console.
"""
os.write(self.fd, data)
On Feb 1, 2004, at 12:28, Bob Ippolito wrote:
> On Feb 1, 2004, at 1:57 PM, Samuel M. Smith wrote:
>
>> Is there an equivalent on mac/unix to the msvcrt module for windows
>> kbhit() function?
>> Or in other words is there some way to do non blocking reads of the
>> terminal as opposed to blocking reads vis a vis raw_input()?
>
> The reason stdin acts as a line based input is because there are
> certain flags set on it... serial ports are the same way. I remember
> delving into this a while ago, and I *think* the constants/functions
> you need to use are in the termios module.
>
> After you've set the right flags, you can even use select() on stdin
> and it'll let you know when a key has been pressed.
>
> -bob
>
> (this is pretty standard *nix stuff..)
>
>
**********************************************************************
Samuel M. Smith Ph.D.
2966 Fort Hill Road
Eagle Mountain, Utah 84043
801-768-2768 voice
801-768-2769 fax
**********************************************************************
"The greatest source of failure and unhappiness in the world is
giving up what we want most for what we want at the moment"
**********************************************************************
More information about the Pythonmac-SIG
mailing list