代码之家  ›  专栏  ›  技术社区  ›  Evan Fosmark

在python中读取单个字符(getch样式)在unix中不起作用

  •  4
  • Evan Fosmark  · 技术社区  · 15 年前

    每次我用这个食谱的时候 http://code.activestate.com/recipes/134892/ 我好像不能让它工作。它总是引发以下错误:

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

    我最好的想法是因为我在Eclipse中运行它,所以 termios 正在对文件描述符进行匹配。

    2 回复  |  直到 15 年前
        1
  •  9
  •   Anurag Uniyal    15 年前

    这是在Ubuntu8.04.1,python 2.5.2上工作的,我没有得到这样的错误。也许您应该从命令行尝试它,Eclipse可能使用它自己的stdin,如果从WingIDE运行它,我会得到完全相同的错误,但是从命令行它工作得很好。 原因是,IDE(例如Wing)使用自己的类netserver.cdbginputstream作为sys.stdin 所以sys.stdin.fileno为零,这就是错误的原因。 基本上,ide stdin不是tty(print sys.stdin.is a tty()为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
  •  4
  •   Vitja Makarov    11 年前

    将终端置于原始模式并不总是一个好主意。事实上,这已经足够清除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()
    
    推荐文章