zoukankan      html  css  js  c++  java
  • Ubuntu终端键盘输入采样(python实现)

    1、设置终端为 raw mode:

    import sys
    from termios import *
    _old_settings = tcgetattr(sys.stdin.fileno())
    IFLAG, OFLAG, CFLAG, LFLAG, ISPEED, OSPEED, CC = 0, 1, 2, 3, 4, 5, 6
    def setraw_input(fd, when=TCSAFLUSH):
        """Put the input of the terminal into a raw mode."""
        mode = tcgetattr(fd)
        mode[IFLAG] = mode[IFLAG] & ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON)
        # mode[OFLAG] = mode[OFLAG] & ~(OPOST)
        mode[CFLAG] = mode[CFLAG] & ~(CSIZE | PARENB)
        mode[CFLAG] = mode[CFLAG] | CS8
        mode[LFLAG] = mode[LFLAG] & ~(ECHO | ICANON | IEXTEN | ISIG)
        mode[CC][VMIN] = 1
        mode[CC][VTIME] = 0
        tcsetattr(fd, when, mode)
        return

      setraw_input 函数参考 python 中的 tty.setraw 函数实现,仅仅取消 OFLAG 的改变,使得终端能够继续处理输出中的特殊字符,以避免输出乱码。

    2、键盘输入采样:

    import select
    def _get_key():
        key ''
        for index in range(0, 10):
            rlist, _, _ = select.select([sys.stdin], [], [], 0)
            if rlist:
                key = sys.stdin.read(1)
        return key
     
     
    import threading, traceback
    _timer = None
    from functools import wraps
    def input_wrap(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            try:
                key = _get_key()
                func(key)
                if key == 'x03':
                    print("ctrl + c")
                    raise Exception("ctrl + c")
                global _timer
                _timer = threading.Timer(0.1, wrapper)
                _timer.start()
            except Exception:
                input_wrap_reset()
            return
        return wrapper

      键盘输入采样频率为 10Hz (0.1s), _get_key 函数中的 for 循环次数计算如下:

    假设键盘输入速率 25char/s (长按不放)
    10 (循环次数) = 25 (输入速率) x 2 (采样定理) x 2 (安全系数) / 10 (采样频率)

    3、自定义键盘输入处理函数:

    @input_wrap
    def print_key(key):
        if key != "":
            print(key)
        return

    4、完整代码:

      input_wrap.py

    #!/usr/bin/env python
     
     
    import sys
    from termios import *
    _old_settings = tcgetattr(sys.stdin.fileno())
    IFLAG, OFLAG, CFLAG, LFLAG, ISPEED, OSPEED, CC = 0, 1, 2, 3, 4, 5, 6
    def setraw_input(fd, when=TCSAFLUSH):
        """Put the input of the terminal into a raw mode."""
        mode = tcgetattr(fd)
        mode[IFLAG] = mode[IFLAG] & ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON)
        # mode[OFLAG] = mode[OFLAG] & ~(OPOST)
        mode[CFLAG] = mode[CFLAG] & ~(CSIZE | PARENB)
        mode[CFLAG] = mode[CFLAG] | CS8
        mode[LFLAG] = mode[LFLAG] & ~(ECHO | ICANON | IEXTEN | ISIG)
        mode[CC][VMIN] = 1
        mode[CC][VTIME] = 0
        tcsetattr(fd, when, mode)
        return
     
     
    def input_wrap_set():
        setraw_input(sys.stdin.fileno())
        return
     
     
    def input_wrap_reset():
        tcsetattr(sys.stdin.fileno(), TCSAFLUSH, _old_settings)
        return
     
     
    import select
    def _get_key():
        key ''
        for index in range(0, 10):
            rlist, _, _ = select.select([sys.stdin], [], [], 0)
            if rlist:
                key = sys.stdin.read(1)
        return key
     
     
    import threading, traceback
    _timer = None
    from functools import wraps
    def input_wrap(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            try:
                key = _get_key()
                func(key)
                if key == 'x03':
                    print("ctrl + c")
                    raise Exception("ctrl + c")
                global _timer
                _timer = threading.Timer(0.1, wrapper)
                _timer.start()
            except Exception:
                input_wrap_reset()
            return
        return wrapper
     
     
    @input_wrap
    def print_key(key):
        if key != "":
            print(key)
        return
     
     
    if __name__ == "__main__":
        input_wrap_set()
        print("hello, world!	hello, world!")
        print_key()
        import time
        try:
            while True:
                time.sleep(1)
        except:
            pass
        finally:
            input_wrap_reset()
        print("hello, world!	hello, world!")
  • 相关阅读:
    [LeetCode in Python] 98 (M) validate binary search tree 验证二叉搜索树
    [LeetCode in Python] 79 (M) word search 单词搜索
    mybatis3源码阅读之SqlSessionFactoryBuilder
    java简单的双色球摇号程序
    低延时直播应用 流媒体
    glPixelStorei 详解 包括像素传输
    depth/stencil buffer的作用 ----------理解模板缓存 opengl
    实用网站汇编
    利用CodeBlocks结合freeglut快速搭建OpenGL开发环境
    opengl 4.5 中文api 链接
  • 原文地址:https://www.cnblogs.com/Ezekiel/p/9067359.html
Copyright © 2011-2022 走看看