【问题标题】:Python curses getch() always returns -1 if data is piped to my program如果数据通过管道传输到我的程序,Python curses getch() 总是返回 -1
【发布时间】:2020-07-19 10:38:30
【问题描述】:

我想读取通过管道传输到我的程序中的数据,然后使用 curses 获取用户输入。我有以下代码:

import curses
import sys
import select

def read_piped_data():
    data = ""
    while(sys.stdin in select.select([sys.stdin,],[],[],0.0)[0]):
        x = sys.stdin.read(1)
        if(len(x) == 0): break
        data += x
    sys.stdin = open("/dev/tty")
    return (data if len(data) > 0 else None)

def main(stdscr):
    data = read_piped_data()
    if(data != None): do_something1(data)
    curses.raw()
    stdscr.keypad(True)
    stdscr.timeout(0)

    while(True):
        ch = stdscr.getch()
        if(ch == -1): continue
        if(not do_something2(stdscr,ch)): break

curses.wrapper(main)

当我执行上述操作时:

$ python3 test.py

一切正常:do_something1() 没有被调用,但do_something2() 每当我按下任意键时都会被调用。但是当我将某些东西管道化为:

$ ls | python3 test.py

我的代码失败:do_something1() 被调用,它正确处理了管道数据,但 do_something2() 从未被调用,我的程序基本上处于无限循环中,没有注册任何按键!

保留或删除sys.stdin = open("/dev/tty") 无效。在另一个 stackoverflow 答案中,我发现这个解决方案可以使 input() 工作(从管道读取后)。虽然在我重新分配标准输入后 input() 可以工作,但 getch() 不能。

即使我不读取管道数据,只需将一些命令管道传输到我的程序就足以弄乱curses getch() 阻止它读取任何按键。

我在 Ubuntu 20.04 上使用 Python 3.8 的 curses。从管道读取后,如何“重新激活”curses 中的输入?

【问题讨论】:

  • 看起来你的 select 循环如果超过输入就会停止,即使稍后可能会有更多输入。这听起来不像是正确的做法。
  • 即使你是对的:在我的特殊情况下(使用“ls”示例),整个管道输出都得到了正确处理。我的问题是 getch()。即使我选择根本不读取管道数据,只需将某些命令的输出管道传输到我的程序就足以让我的 curses getch() 无法读取任何内容!
  • 重新分配sys.stdin 不会改变程序的实际标准输入。您可能不得不弄乱文件描述符和os.dup2

标签: python python-3.x python-curses


【解决方案1】:

也许是因为标准输入不能保证是可分配的? 在 C,我对此没有任何问题:

freopen("/dev/tty","r",stdin);

用 fopen 重新分配也在这里工作。

【讨论】:

  • 我认为有 python 等价物。我不知道。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-13
  • 1970-01-01
  • 2015-10-08
  • 1970-01-01
相关资源
最近更新 更多