【问题标题】:Python 3: Capture return of `\x1b[6n` (`\033[6n`, `\e[6n`) ansi sequencePython 3:捕获返回的`\x1b[6n` (`\033[6n`, `\e[6n`) ansi 序列
【发布时间】:2016-07-19 17:43:14
【问题描述】:

我正在写一个“libansi”。 我想捕获ansi序列\x1b[6n的返回码 我尝试了一些解决方法,但无事可做。

示例:

#!/usr/bin/python3.4
rep = os.popen("""a=$(echo "\033[6n") && echo $a""").read()

rep 返回 "\033[6n"...

有人有想法吗?

感谢您的帮助。

编辑: 我有一个部分解决方案:

a=input(print("\033[6n", end='')

但这需要我在输入时按“输入”才能获得光标位置。

【问题讨论】:

  • 所有像这样的解决方案都无法工作,因为 sh/bash cmd 中的 ANSI 序列在子 shell 中回显。

标签: python terminal python-3.4 ansi-escape


【解决方案1】:

问题是

  1. 默认情况下标准输入是缓冲的,并且
  2. 将序列写入标准输出后,终端会将其响应发送到标准输入,而不是标准输出。所以终端的行为就像按下实际键而没有返回。

诀窍是使用tty.setcbreak(sys.stdin.fileno(), termios.TCSANOW) 并在此之前通过termios.getattr 将终端属性存储在变量中以恢复默认行为。使用cbreak 设置,os.read(sys.stdin.fileno(), 1) 您可以立即从标准输入读取。这也抑制了来自终端的 ansi 控制代码响应。

def getpos():

    buf = ""
    stdin = sys.stdin.fileno()
    tattr = termios.tcgetattr(stdin)

    try:
        tty.setcbreak(stdin, termios.TCSANOW)
        sys.stdout.write("\x1b[6n")
        sys.stdout.flush()

        while True:
            buf += sys.stdin.read(1)
            if buf[-1] == "R":
                break

    finally:
        termios.tcsetattr(stdin, termios.TCSANOW, tattr)

    # reading the actual values, but what if a keystroke appears while reading
    # from stdin? As dirty work around, getpos() returns if this fails: None
    try:
        matches = re.match(r"^\x1b\[(\d*);(\d*)R", buf)
        groups = matches.groups()
    except AttributeError:
        return None

    return (int(groups[0]), int(groups[1]))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-16
    • 1970-01-01
    • 2021-09-20
    • 1970-01-01
    • 2013-02-07
    • 2016-09-09
    • 1970-01-01
    • 2021-06-30
    相关资源
    最近更新 更多