How to get user input during a while loop without blocking

后端 未结 3 1639
说谎
说谎 2020-12-10 22:18

I\'m trying to write a while loop that constantly updates the screen by using os.system(\"clear\") and then printing out a different text message every few seconds. How do I

相关标签:
3条回答
  • 2020-12-10 23:04

    You can also check one of the recipes available out there, which gives you the functionality you're looking for for both Unix and Windows.

    0 讨论(0)
  • 2020-12-10 23:06

    You can do that with threads, here is a basic example :

    import threading, os, time, itertools, Queue
    
    # setting a cross platform getch like function
    # thks to the Python Cookbook
    # why isn't standard on this battery included language ?
    try : # on windows
        from msvcrt import getch
    except ImportError : # on unix like systems
        import sys, tty, termios
        def getch() :
            fd = sys.stdin.fileno()
            old_settings = termios.tcgetattr(fd)
            try :
                tty.setraw(fd)
                ch = sys.stdin.read(1)
            finally :
                termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
            return ch
    
    # this will allow us to communicate between the two threads
    # Queue is a FIFO list, the param is the size limit, 0 for infinite
    commands = Queue.Queue(0)
    
    # the thread reading the command from the user input     
    def control(commands) :
    
        while 1 :
    
            command = getch()
            commands.put(command) # put the command in the queue so the other thread can read it
    
            #  don't forget to quit here as well, or you will have memory leaks
            if command == "q" :
                break
    
    
    # your function displaying the words in an infinite loop
    def display(commands):
    
        string = "the fox jumped over the lazy dog"
        words = string.split(" ")
        pause = False 
        command = ""
    
        # we create an infinite generator from you list
        # much better than using indices
        word_list = itertools.cycle(words) 
    
        # BTW, in Python itertools is your best friend
    
        while 1 :
    
            # parsing the command queue
            try:
               # false means "do not block the thread if the queue is empty"
               # a second parameter can set a millisecond time out
               command = commands.get(False) 
            except Queue.Empty, e:
               command = ""
    
            # behave according to the command
            if command == "q" :
                break
    
            if command == "p" :
                pause = True
    
            if command == "r" :
                pause = False
    
            # if pause is set to off, then print the word
            # your initial code, rewritten with a generator
            if not pause :
                os.system("clear")
                print word_list.next() # getting the next item from the infinite generator 
    
            # wait anyway for a second, you can tweak that
            time.sleep(1)
    
    
    
    # then start the two threads
    displayer = threading.Thread(None, # always to None since the ThreadGroup class is not implemented yet
                                display, # the function the thread will run
                                None, # doo, don't remember and too lazy to look in the doc
                                (commands,), # *args to pass to the function
                                 {}) # **kwargs to pass to the function
    
    controler = threading.Thread(None, control, None, (commands,), {})
    
    if __name__ == "__main__" :
        displayer.start()
        controler.start()
    

    As usual, using threads is tricky, so be sure you understand what you do before coding that.

    Warning : Queue will be rename in queue in Python 3.

    0 讨论(0)
  • 2020-12-10 23:17

    The select module in Python's standard library may be what you're looking for -- standard input has FD 0, though you may also need to put a terminal in "raw" (as opposed to "cooked") mode, on unix-y systems, to get single keypresses from it as opposed to whole lines complete with line-end. If on Windows, msvcrt, also in Python standard library, has all the functionality you need -- msvcrt.kbhit() tells you if any keystroke is pending, and, if so, msvcrt.getch() tells you what character it is.

    0 讨论(0)
提交回复
热议问题