python非阻塞非混乱-my-tty按键检测 [英] python non-blocking non-messing-my-tty key press detection

查看:34
本文介绍了python非阻塞非混乱-my-tty按键检测的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个循环可以做一些工作并将很多信息打印到标准输出.一遍又一遍(这是一个循环......)我想要做的是检测用户何时/是否按下一个键(它可以是箭头、输入或字母),并在发生这种情况时做一些工作.

I have a loop that does some work and prints a lot of info to stdout. Over and over again (it's a loop...) What I'd like to do is to detect when / if user presses a key (it can be an arrow, enter, or a letter), and do some work when that happens.

这应该是一个非常简单的子任务,但我花了四个小时尝试不同的方法,但几乎一无所获.

This should have been a very simple subsubtask, but I've spent last four hours trying different approaches and getting pretty much nowhere.

这只需要在 Linux 中工作.

This needs only work in Linux.

我能得到的最好的东西是下面这样的.但这部分起作用,只有在 0.05 秒内才能捕获密钥.

Best I could get is something like this below. But that works partially, catching the keys only if within the 0.05 sec.

import sys,tty,termios
class _Getch:
    def __call__(self, n=1):
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
            tty.setraw(sys.stdin.fileno())
            ch = sys.stdin.read(n)
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
        return ch


def getch(timeout=0.2):
    inkey = _Getch()
    k = ''
    start_sec = time()
    while(time() - start_sec < timeout):
        if k == '':
            k = timeout_call(inkey, timeout_duration=timeout - (time() - start_sec))
    if k == u'\x1b':
        k += inkey(2)
        if k == u'\x1b[A':
            return "up"
        if k == u'\x1b[B':
            return "down"
        if k == u'\x1b[C':
            return "right"
        if k == u'\x1b[D':
            return "left"
    elif k == "q":
        return 'q'
    elif k == "\n":
        return 'enter'
    else:
        return None


while True:
    do_some_work_that_lasts_about_0_2_seconds()
    key = getch(0.05)
    if key:
        do_something_with_the(key)

推荐答案

这已经被问过了.有人发布了一个不错的、简短的、重构的解决方案

This has been asked before. Someone posted a nice, short, refactored solution

在此转发

import sys
import select
import tty
import termios

class NonBlockingConsole(object):

    def __enter__(self):
        self.old_settings = termios.tcgetattr(sys.stdin)
        tty.setcbreak(sys.stdin.fileno())
        return self

    def __exit__(self, type, value, traceback):
        termios.tcsetattr(sys.stdin, termios.TCSADRAIN, self.old_settings)


    def get_data(self):
        if select.select([sys.stdin], [], [], 0) == ([sys.stdin], [], []):
            return sys.stdin.read(1)
        return False


if __name__ == '__main__':
    # Use like this
    with NonBlockingConsole() as nbc:
        i = 0
        while 1:
            print i
            i += 1

            if nbc.get_data() == '\x1b':  # x1b is ESC
                break

这篇关于python非阻塞非混乱-my-tty按键检测的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆