繁体   English   中英

如何在while循环期间获取用户输入而不阻塞

[英]How to get user input during a while loop without blocking

我正在尝试编写一个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'分别退出和暂停。

Python标准库中的select模块可能正是您所需要的 - 标准输入具有FD 0,但您可能还需要在unix-y上将终端设置为“raw”(而不是“cooked”)模式系统,从它获得单个按键,而不是整行与行结束。 如果在Windows上, msvcrt (也在Python标准库中)具有您需要的所有功能 - msvcrt.kbhit()告诉您是否有任何键击未决,如果是, msvcrt.getch()告诉您它是什么字符。

您还可以查看其中一个可用的配方 ,它为您提供了Unix和Windows所需的功能。

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

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中重命名为队列。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM