【问题标题】:Get user input while reading STDIN from a pipe?从管道读取 STDIN 时获取用户输入?
【发布时间】:2017-09-27 07:12:47
【问题描述】:

我正在编写一个命令行工具(我们称之为interactive_rm),它应该从 STDIN 逐行读取文件路径,以便它可以与 Unix 管道一起使用,例如下面的例子:

$ find . | interactive_rm

我目前正在像这样从 STDIN 读取每个路径:

def _parse_stdin():
    for line in sys.stdin:
        yield prepare_line(line)

现在的问题...在工具删除路径之前,它应该要求用户确认。为此,我会像这样使用input()

for path in _parse_stdin():
    print('Do you want to delete this path: [y/n]\n' + path)
    answer = input()
    if answer == 'y':
        delete(path)

但这不起作用,因为 STDIN 已经被管道占用了,所以 input() 函数被跳过或者我最终得到一个“EOFError: EOF when reading a line”

有人知道解决办法吗?

【问题讨论】:

    标签: python unix input pipe stdin


    【解决方案1】:

    stdin被重定向时,需要重新打开终端才能读取,例如:

    from __future__ import print_function
    
    import os
    
    def main():
        tty = os.open("/dev/tty", os.O_RDONLY)
        while True:
            r = os.read(tty, 1024)
            if not r: # Wait for Ctrl-D.
                break
            print("----", r)
    
    if __name__ == "__main__":
        main()
    

    然后像下面这样运行它来测试它:

    python t.py < /dev/null
    

    请注意,终端可能不可用。例如,如果命令通过 ssh 会话运行,而没有将终端分配为 ssh -T ... command

    【讨论】:

    • 这应该是现在公认的答案。
    最近更新 更多