How to read a single character from the user?

后端 未结 23 2684
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-11-21 04:28

Is there a way of reading one single character from the user input? For instance, they press one key at the terminal and it is returned (sort of like getch()).

23条回答
  •  梦谈多话
    2020-11-21 05:04

    Try using this: http://home.wlu.edu/~levys/software/kbhit.py It's non-blocking (that means that you can have a while loop and detect a key press without stopping it) and cross-platform.

    import os
    
    # Windows
    if os.name == 'nt':
        import msvcrt
    
    # Posix (Linux, OS X)
    else:
        import sys
        import termios
        import atexit
        from select import select
    
    
    class KBHit:
    
        def __init__(self):
            '''Creates a KBHit object that you can call to do various keyboard things.'''
    
            if os.name == 'nt':
                pass
    
            else:
    
                # Save the terminal settings
                self.fd = sys.stdin.fileno()
                self.new_term = termios.tcgetattr(self.fd)
                self.old_term = termios.tcgetattr(self.fd)
    
                # New terminal setting unbuffered
                self.new_term[3] = (self.new_term[3] & ~termios.ICANON & ~termios.ECHO)
                termios.tcsetattr(self.fd, termios.TCSAFLUSH, self.new_term)
    
                # Support normal-terminal reset at exit
                atexit.register(self.set_normal_term)
    
    
        def set_normal_term(self):
            ''' Resets to normal terminal.  On Windows this is a no-op.
            '''
    
            if os.name == 'nt':
                pass
    
            else:
                termios.tcsetattr(self.fd, termios.TCSAFLUSH, self.old_term)
    
    
        def getch(self):
            ''' Returns a keyboard character after kbhit() has been called.
                Should not be called in the same program as getarrow().
            '''
    
            s = ''
    
            if os.name == 'nt':
                return msvcrt.getch().decode('utf-8')
    
            else:
                return sys.stdin.read(1)
    
    
        def getarrow(self):
            ''' Returns an arrow-key code after kbhit() has been called. Codes are
            0 : up
            1 : right
            2 : down
            3 : left
            Should not be called in the same program as getch().
            '''
    
            if os.name == 'nt':
                msvcrt.getch() # skip 0xE0
                c = msvcrt.getch()
                vals = [72, 77, 80, 75]
    
            else:
                c = sys.stdin.read(3)[2]
                vals = [65, 67, 66, 68]
    
            return vals.index(ord(c.decode('utf-8')))
    
    
        def kbhit(self):
            ''' Returns True if keyboard character was hit, False otherwise.
            '''
            if os.name == 'nt':
                return msvcrt.kbhit()
    
            else:
                dr,dw,de = select([sys.stdin], [], [], 0)
                return dr != []
    

    An example to use this:

    import kbhit
    
    kb = kbhit.KBHit()
    
    while(True): 
        print("Key not pressed") #Do something
        if kb.kbhit(): #If a key is pressed:
            k_in = kb.getch() #Detect what key was pressed
            print("You pressed ", k_in, "!") #Do something
    kb.set_normal_term()
    

    Or you could use the getch module from PyPi. But this would block the while loop

提交回复
热议问题