从“stdin”读取文件后如何使用“input()”?

2024-05-07

Context

我想要一个简单的脚本,它可以选择多个管道输入中的一个,而不需要EOF when reading a lineUnix/Linux 上的错误。

它试图:

  1. 接受多行管道文本
  2. 等待用户选择一个选项
  3. 将该选项打印到标准输出

所需用途:

$ printf "A\nB" | ./select.py | awk '{print "OUTPUT WAS: " $0}'
Select 0-1:
  0) A
  1) B
> 1
OUTPUT WAS: B

The awk '{print "[OUTPUT WAS] " $0}'最后只是为了表明唯一的标准输出输出应该是选择。

目前的方法:

#!/bin/python3
import sys
from collections import OrderedDict

def print_options(options):
    """print the user's options"""
    print(f"Select 0-{len(options)-1}:", file=sys.stderr)
    for n, option in options.items():
        print(f"  {n}) {option}", file=sys.stderr)

def main():
    # options are stored in an ordered dictionary to make order consistent
    options = OrderedDict()
    # read in the possible options one line at a time
    for n, line in enumerate(sys.stdin):
        options[n] = line.rstrip('\n')
        
    valid_selection = False
    # loop until we get a valid selection
    while not valid_selection:
        print_options(options)
        try:
            print('> ', end='', file=sys.stderr)
            selection = int(input()) # <- doesn't block like it should
            # use the selection to extract the output that will be printed
            output = options[selection]
            valid_selection = True
        except Exception as e:
            print(f"Invalid selection. {e}", file=sys.stderr)
                
    print(output)

if __name__ == '__main__':
    main()

Error:

该脚本陷入无限循环打印:

...
> Invalid selection. EOF when reading a line
Select 0-1:
  0) A
  1) B
> Invalid selection. EOF when reading a line
Select 0-1:
  0) A
  1) B
> Invalid selection. EOF when reading a line
...

重现错误的最小脚本:

#!/bin/python3
import sys

options = []
# read in the possible options one line at a time
for line in sys.stdin:
    options.append(line.rstrip('\n'))
    
user_input = input('> ')
            
print(user_input)

这会抛出:

EOFError: EOF when reading a line

当我想查看并输入时:

$ printf "text" | ./testscript.py
> sometext
sometext

所需的解决方案:

我认为这是因为 stdin 已达到 EOF。但我的问题是如何重置/消除 EOF 的影响,以便input()再次像平常一样阻塞并等待用户。

简而言之:如何使用input()读取文件后stdin?

如果那是不可能的话正如这个答案所暗示的 https://stackoverflow.com/a/6833677/7872793,有什么优雅的解决方案可以得到与我在这个问题开头描述的类似的行为?我对非 python 解决方案持开放态度(例如 bash|zsh、rust、awk、perl)。


我可以回答你关于 Linux/Unix 操作系统的问题。抱歉,我不使用 Windows。

我在示例代码中添加了两行,请参见下文。

特殊装置/dev/tty已连接到您的终端。除非重定向,否则它是您的标准输入/输出。基本上,您想要恢复标准输入连接到终端的状态。在底层,它与文件描述符 0 一起工作。close关闭它并且open获取第一个空闲的,在这种情况下是 0。

import sys 

options = []
# read in the possible options one line at a time
for line in sys.stdin:
    options.append(line.rstrip('\n'))

# restore input from the terminal   
sys.stdin.close()
sys.stdin=open('/dev/tty')

user_input = input('> ')
                 
print(user_input)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从“stdin”读取文件后如何使用“input()”? 的相关文章

随机推荐