3

Is there a way to accept only numbers in Python, say like using raw_input()?

I know I can always get the input and catch a ValueError exception, but I was interested in knowing whether there was someway I could force the prompt to accept only numbers and freeze on any other input.

6
  • Why would you want to do that? Commented Jun 29, 2010 at 20:38
  • I am making a small script that accepts marks as input. Commented Jun 29, 2010 at 20:40
  • You could probably write your own class that does that, I don't think there's any such built-in feature. Commented Jun 29, 2010 at 20:42
  • @Alfred: I've done the same thing, writing a grading script. Just raise a ValueError on non-numeric input. Commented Jun 29, 2010 at 20:44
  • @David: Aah! I thought there had to be a way in Python. Commented Jun 29, 2010 at 20:49

2 Answers 2

2

From the docs:

How do I get a single keypress at a time?

For Unix variants: There are several solutions. It’s straightforward to do this using curses, but curses is a fairly large module 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.

Using this, you could grab the character, check if it's a number, and then display it. I haven't tried it myself, though.

Sign up to request clarification or add additional context in comments.

Comments

0

As far as I know, no. I've never heard of such a thing being possible with a terminal, in Python or any other language.

The closest way I can think of to fake it would be to put the terminal in silent mode (so that input characters are not echoed) and unbuffered mode (so that you get each character typed as it's typed, without waiting for the end of the line), then read each input character one by one; if it's a digit, print it and append it to a string, otherwise discard it. But I'm not even sure if the terminal would allow you to do that.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.