Python CLI脚本中的pipe道和提示

是否可以在Python CLI脚本中结合pipe道input和TTY提示? 例如,运行这个:

import sys piped_text = None if not sys.stdin.isatty(): piped_text = sys.stdin.read() user_in = raw_input('Enter something: ') if piped_text: sys.stdout.write(piped_text) sys.stdout.write(user_in + '\n') 

生成以下输出:

 ~: python mrprompt.py Enter something: something something ~: echo foo | python mrprompt.py Enter something: Traceback (most recent call last): File "mrprompt.py", line 9, in <module> user_in = raw_input('Enter something: ') EOFError: EOF when reading a line 

当我正在寻找的输出是这样的:

 ~: python mrprompt.py Enter something: something something ~: echo foo | python mrprompt.py Enter something: something foo something 

我猜,措辞不同,是否有可能的一个子shell知道它的父shell的tty? 在Python中,是否有可能与父shell的tty交互? 我在GNU Screen中使用bash(因此,读取“SSH_TTY”环境variables不是一个可行的选项)。

这或多或少地起作用:

 #!/usr/bin/python import sys saved_stdin = sys.stdin sys.stdin = open('/dev/tty', 'r') result = raw_input('Enter something: ') sys.stdout.write('Got: ' + result + '\n') sys.stdin = saved_stdin result2 = sys.stdin.read() sys.stdout.write('Also got: ' + result2) 

保存为foo.py然后尝试echo goodbye | ./foo.py echo goodbye | ./foo.py

当然, /dev/tty只存在于Unix上。 如果你在没有控制终端的过程中运行它, open()可能会失败。

你可以检测你的stdin是否来自管道,就像使用sys.stdin.isatty 。 你得到了EOF因为你用stdin.read()读取了所有的输入,然后用raw_input()命令尝试读更多的东西。

你不能做的是管道输入和交互输入。 如果你输入管道输入,没有其他的stdinraw_input工作。 唯一的stdin是来自文件的。

你需要做的是提供一个可选的方法来让你的脚本的相应部分从一个文件中读取输入,并使用类似的开关

 --input=file.txt 

然后为其他部分提供交互提示。

可以在同一个程序中同时接受管道输入和用户输入。

处理这个最简单的方法是使用subprocess模块。 您将从您的Python程序中执行该程序。 它的参数允许你设置管道和/或从正在执行的程序中。

很简单。 这是标准的。 它运作良好。

通过程序参数接收文件也是如此。 很简单。 这是标准的。 它运作良好。 作为一个额外的好处,在Windows CMD.EXE / COMMAND.COM自动使用管道的临时文件。 由于DOS / Windows不支持真正的管道,你不会得到任何更复杂的好处。

我知道命令行mysql客户端代码在处理管道输入之前接受用户的密码。 Linux(也许是Mac OS X)解决方案可能与Nemo发布的类似。 如果这是你真正想要的行为,而且你不关心Windows,那就是使用的解决方案。 (对于Windows,你需要使用类似wconio包的东西 – http://newcenturycomputers.net/projects/wconio.html

可能有用户输入,并接受管道输出另一个程序。 有三个标准的文件句柄:stdin,stdout和stderr。 即使将stdout重定向到文件,也可以写入stderr。