简体   繁体   English

如何在标准输入中使用 Python 诅咒?

[英]How can I use Python curses with stdin?

I am trying to write a Python program, which show/edit text from stdin using curses.我正在尝试编写一个 Python 程序,它使用curses显示/编辑来自标准输入的文本。 I cloud implement edit module, but I couldn't stdin as input.我云实现了编辑模块,但我无法将标准输入作为输入。

How can I solve this problem?我怎么解决这个问题?

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

And python edit.py (without echo "hello") is successfully complete.并且python edit.py (没有 echo "hello")成功完成。

First you must read your data from stdin and not from curses.getkey() since you piped them.首先,您必须从标准输入读取数据,而不是从 curses.getkey() 读取数据,因为您使用管道传输它们。

So you can do this to read the stdin first then init and then display the content in curses:所以你可以这样做先读取标准输入然后初始化,然后在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)

You can launch:您可以启动:

$ echo "hello" | python edit.py

And everything is fine, you show the line or the lines (if you cat something with multiple lines) you pass to your script in ncurses.一切都很好,你显示你在 ncurses 中传递给你的脚本的一行或多行(如果你用多行来处理cat东西)。

BUT there is this issue where getch() is not working if you read stdin before, so you won't be able to quit with 'q' even tho it's supposed to do so.但是如果您之前阅读标准输入,getch() 将无法正常工作,因此即使应该这样做,您也无法使用 'q' 退出。

This subject has been answered by @Frédéric Hamidi here: Linux: Pipe into Python (ncurses) script, stdin and termios Read his answer for further detail but basically you have to dup the stdin. @Frédéric Hamidi 在这里回答了这个问题: Linux: Pipe 到 Python 他的答案(ncurses)脚本,stdin 和 termdup基本上可以阅读更多详细信息

Add this line right after reading stdin in main :main中读取 stdin 后立即添加此行:

os.dup2(3, 0)

And instead of calling like this:而不是这样调用:

$ echo "hello" | python edit.py

Call like this:像这样调用:

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

Or alternatively spawn the subshell before like this:或者在像这样之前生成子shell:

$ exec 3<&0  

And then call normally然后正常调用

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

You can read the answers linkeda and the docs for further understanding.您可以阅读链接的答案和文档以进一步理解。 Hope this helps anyway.无论如何,希望这会有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM