使用curses立即检测用户输入

时间:2015-08-21 09:25:57

标签: python python-2.7 curses

我在python2.7中使用curses来控制机器人。我想引导它,例如w键,告诉它它应该继续前进。这是我的代码,剥离了所有机器人控件:

import curses
from time import sleep

if __name__ == "__main__":
    shell = curses.initscr()
    shell.nodelay(True)

    while True:
        key = shell.getch()

        if key == 119:
            print("key w pressed")

        sleep(0.03)

工作正常,但我必须按Enter键才能识别密钥。所以我可以按w几次,当我按下回车键时,机器人完全按照它应该做的那样,或者在这个例子中,文本key w pressed出现的次数与我一样多次压了它。但我希望这会立即发生,即无需按Enter键。如何实现这一目标?

3 个答案:

答案 0 :(得分:1)

RHEL添加到您的设置中,清理时调用curses.cbreak()将终端恢复到可用状态。

您可以通过将 ctrl-c 作为例外进行清理。例如:

curses.nocbreak()

答案 1 :(得分:1)

鉴于OP未使用window.keypad,调用curses.rawcurses.cbreak会给(几乎)相同的结果以允许脚本读取无缓冲的字符。

调用curses.endwin()是一种更可靠的恢复方法。请记住,它是诅咒的包装。 curses 模拟 cbreak模式,将实际终端模式设置为 raw 。调用curses.nocbreak对实际终端模式有 no 效果。

如果您致电nocbreak进行清理而不是致电endwin,则还需要解决其他问题(例如,请参阅Clean up ncurses mess in terminal after a crash),因为终端将处于原始模式(包括真实noecho,这使得输入stty sane^M很痛苦。

参考endwin的文档,

  

程序应始终在退出或暂时退出curses模式之前调用 endwin 。这个例程

   o   restores tty modes,

   o   moves the cursor to the lower left-hand corner of  the
       screen and

   o   resets the terminal into the proper non-visual mode. 

如上所述,cbreakraw 几乎相同。主要区别在于程序如何响应键盘中断(如^C)。如果您正在使用ncurses,则会设置signal handlersSIGINTSIGTERM)会调用curses.endwin。其他curses实现不执行此操作,即使您的脚本调用curses.endwin,也不确定它是否会按预期工作(因为curses倾向于调用不安全的流I / O函数,这些函数无法在信号处理程序中可靠地使用)。

答案 2 :(得分:1)

现有答案正确,cbreak()将关闭缓冲输入模式,这意味着getch()将立即返回按键。

我建议使用curses.wrapper()函数。在这种情况下,可以设置屏幕并进行缓冲。但是它还会捕获异常,并确保在应用程序退出时将终端返回到干净状态。阅读有关here

基于OPs代码的示例为:

import curses
from time import sleep

def program_loop(stdscr):
    while True:
        key = stdscr.getch()


        if key == 119:
            print("key w pressed\r")

        sleep(0.03)

if __name__ == "__main__":
    curses.wrapper(program_loop)