首页 > 解决方案 > 如何在标准输入中使用 Python 诅咒?

问题描述

我正在尝试编写一个 Python 程序,它使用 curses 从标准输入显示/编辑文本。我云实现了编辑模块,但我无法将标准输入作为输入。

我怎么解决这个问题?

import curses

def main(stdscr):
    while key := stdscr.getkey():
        stdscr.addstr(0, 0, key)

if __name__ == '__main__':
    curses.wrapper(main)
echo "hello" | python edit.py

Traceback (most recent call last):
  File "/path/to/edit.py", line 8, in <module>
    curses.wrapper(main)
  File "/path/to/.pyenv/versions/3.9.1/lib/python3.9/curses/__init__.py", line 94, in wrapper
    return func(stdscr, *args, **kwds)
  File "/path/to/edit.py", line 4, in main
    while key := stdscr.getkey():
_curses.error: no input

并且python edit.py(没有 echo "hello")成功完成。

标签: pythoncurses

解决方案


首先,您必须从标准输入读取数据,而不是从 curses.getkey() 读取数据,因为您使用管道传输它们。

所以你可以这样做先读取标准输入然后初始化,然后在 curses 中显示内容:

import sys
import curses

stdin_content = ()

def main(stdscr):
    stdscr.clear() # and other curses init...
    while True:
        for i, line in enumerate(stdin_content):
            stdscr.addstr(2 + i, 2, "> " + line)
        stdscr.refresh()
        key = stdscr.getch()
        stdscr.timeout(1000)
        if key == ord('q'):
            break

if __name__ == '__main__':
    stdin_content = sys.stdin.readlines()
    curses.wrapper(main)

您可以启动:

$ echo "hello" | python edit.py

一切都很好,你在 ncurses 中显示你传递给你的脚本的一行或多行(如果你cat有多行的话)。

但是如果您之前阅读过标准输入,则会出现 getch() 不起作用的问题,因此即使应该这样做,您也无法使用 'q' 退出。

@Frédéric Hamidi 在这里回答了这个问题: Linux:管道到 Python (ncurses) 脚本、stdin 和 termios 阅读他的答案以获取更多详细信息,但基本上你必须复制标准输入。

在main中读取 stdin 后立即添加此行:

os.dup2(3, 0)

而不是这样调用:

$ echo "hello" | python edit.py

像这样调用:

$ (echo "hello" | python edit.py) 3<&0

或者像这样在之前生成子shell:

$ exec 3<&0  

然后正常调用

$ echo "hello" | python edit.py
$ cat test.txt | python edit.py

您可以阅读链接的答案和文档以进一步理解。无论如何,希望这会有所帮助。


推荐阅读