【问题标题】:How to get user input during a while loop without blocking如何在while循环期间获取用户输入而不阻塞
【发布时间】:2009-08-11 05:27:05
【问题描述】:

我正在尝试编写一个 while 循环,该循环通过使用 os.system("clear") 不断更新屏幕,然后每隔几秒钟打印出一条不同的文本消息。如何在循环期间获取用户输入? raw_input() 只是暂停和等待,这不是我想要的功能。

import os
import time

string = "the fox jumped over the lazy dog"
words = string.split(" ")
i = 0 

while 1:
    os.system("clear")
    print words[i]
    time.sleep(1)
    i += 1
    i = i%len(words)

我希望能够按中间的“q”或“p”分别退出和暂停。

【问题讨论】:

  • 与您的问题无关:请注意 string.split() 可以更简单地替换 string.split(" ")。
  • @EOL: string.split()string.split(" ") 不是一回事。
  • 这很酷,一个有 1 个代表的家伙进来,打针,拿走然后离开。喜欢那个。
  • 嘿,e-satis,看来我违反了社区的某些规则。对不起。正如您所观察到的,我是新来的,不确定事情是如何运行的。我一直在度假,无法完成这个问题所解决的任务,因此任何反馈或感谢都是不知情的。您能否指出相当于礼仪常见问题解答的内容?

标签: python


【解决方案1】:

Python 标准库中的 select 模块可能是您正在寻找的——标准输入具有 FD 0,尽管您可能还需要将终端置于“原始”(而不是“熟”)模式,在 unix-y 系统上,从中获取单个按键,而不是完整的行与行结束。如果在 Windows 上,msvcrt(也在 Python 标准库中)具有您需要的所有功能——msvcrt.kbhit() 会告诉您是否有任何按键未完成,如果是,msvcrt.getch() 会告诉您它是什么字符。

【讨论】:

    【解决方案2】:

    您还可以查看one of the recipes,那里提供了您正在寻找的适用于 Unix 和 Windows 的功能。

    【讨论】:

      【解决方案3】:

      你可以用线程做到这一点,这是一个基本的例子:

      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()
      

      像往常一样,使用线程是很棘手的,所以在编写代码之前一定要了解自己的工作。

      警告:队列将在 Python 3 中重命名。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-12-09
        • 2013-10-05
        • 1970-01-01
        • 1970-01-01
        • 2014-12-31
        • 2018-03-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多