如何判断非阻塞stdin的读取量?

时间:2016-02-22 04:14:29

标签: python command-line-interface

msvcrt有一个方便的功能:kbhit()。 Unix没有:(

我有一个函数_Getch(),如:

def _Getch():
    if sys.stdin.isatty():
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
            tty.setraw(sys.stdin.fileno())
            ch = sys.stdin.read(1)
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
            return ch
    else:
        return sys.stdin.read(1)

它只有一个按键。

当有人按下时出现问题:

  • ESC 发送\x1b。那是 1个字节:实际的转义字符。

  • Page Up 发送\x1b[H。那是 3个字节

  • F2 发送\x1b[OQ。那是 4个字节

  • F5 发送\x1b[15~。那是 5个字节

看看这是怎么回事?一旦读取了ESC,就无法预测以下序列将持续多长时间。

后续_Getch()次调用获取这些字节,但问题是多少次 _Getch()次调用。

我想要定义一个类似下面的函数,它将读取在stdin中等待的所有内容,直到没有任何内容:

def _Kbhit():
    y = []
    while msvcrt.kbhit():         # while something is waiting
        y.append(msvcrt.getch())  # get it!
    return y

这是我的目标(from here)的Unix等价物:

def _Kbhit():
    fd = sys.stdin.fileno()
    fl = fcntl.fcntl(fd, fcntl.F_GETFL)
    fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
    return sys.stdin.read(waiting_buffer_len)  # ?

我只是不知道如何定义waiting_buffer_len

我搜索了所有相关文档(ttytermiossys.stdinfcntlos),但我找不到我正在寻找什么。

1 个答案:

答案 0 :(得分:0)

由于this answer

,我做了更多的搜索和不直观的搜索
  

在查看sys.stdin.read的帮助文档时,我注意到了   这样:

     
    

读(...)

         

read([size]) - >读取最多大小字节,以字符串形式返回。

         

如果size参数为负数或省略,则读取直至EOF为     到达。请注意,在非阻塞模式下,数据少于什么     被请求可能会被退回,即使没有给出尺寸参数。

  

答案是waiting_buffer_len可以是任何长度:

def _Kbhit():
    fd = sys.stdin.fileno()
    fl = fcntl.fcntl(fd, fcntl.F_GETFL)
    fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
    try:
        chars = sys.stdin.read(10)
    except TypeError:
        chars = ""
    finally:
        fcntl.fcntl(fd, fcntl.F_SETFL, fl)
        return chars

完美无缺。