【问题标题】:Reading a single character (getch style) in Python is not working in Unix在 Python 中读取单个字符(获取样式)在 Unix 中不起作用
【发布时间】:2013-07-30 14:21:12
【问题描述】:

每当我使用http://code.activestate.com/recipes/134892/ 的食谱时,我似乎都无法让它发挥作用。它总是抛出以下错误:

Traceback (most recent call last):
    ...
    old_settings = termios.tcgetattr(fd)
termios.error: (22, 'Invalid argument)

我最好的想法是因为我在 Eclipse 中运行它,所以termios 对文件描述符很不满意。

【问题讨论】:

    标签: python getch


    【解决方案1】:

    这适用于 Ubuntu 8.04.1、Python 2.5.2,我没有收到此类错误。也许你应该从命令行尝试它,eclipse 可能使用它自己的标准输入,如果我从 Wing IDE 运行它,我会得到完全相同的错误,但从命令行它工作得很好。 原因是 IDE 例如 Wing 正在使用自己的类 netserver.CDbgInputStream 作为 sys.stdin 所以 sys.stdin.fileno 为零,这就是错误的原因。 基本上 IDE 标准输入不是 tty(打印 sys.stdin.isatty() 是 False)

    class _GetchUnix:
        def __init__(self):
            import tty, sys
    
        def __call__(self):
            import sys, tty, termios
            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
    
    
    getch = _GetchUnix()
    
    print getch()
    

    【讨论】:

    • 不适用于箭头键 - 在缓冲区中留下多余的字符。
    【解决方案2】:

    将终端置于原始模式并不总是一个好主意。实际上,清除 ICANON 位就足够了。这是另一个支持超时的 getch() 版本:

    import tty, sys, termios
    import select
    
    def setup_term(fd, when=termios.TCSAFLUSH):
        mode = termios.tcgetattr(fd)
        mode[tty.LFLAG] = mode[tty.LFLAG] & ~(termios.ECHO | termios.ICANON)
        termios.tcsetattr(fd, when, mode)
    
    def getch(timeout=None):
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
            setup_term(fd)
            try:
                rw, wl, xl = select.select([fd], [], [], timeout)
            except select.error:
                return
            if rw:
                return sys.stdin.read(1)
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
    
    if __name__ == "__main__":
        print getch()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-03
      • 1970-01-01
      • 1970-01-01
      • 2023-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多