Python CLI脚本中的管道和提示

jor*_*lli 5 python linux

是否可以在Python CLI脚本中组合管道输入和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')  
Run Code Online (Sandbox Code Playgroud)

产生以下输出:

~: 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
Run Code Online (Sandbox Code Playgroud)

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

~: python mrprompt.py
Enter something: something
something
~: echo foo | python mrprompt.py
Enter something: something
foo
something
Run Code Online (Sandbox Code Playgroud)

我想,换句话说,子shell是否有可能知道其父shell的tty?在Python中,是否有可能与父shell的tty进行交互?我在GNU Screen中使用bash(因此,读取'SSH_TTY'环境变量不是一个可行的选择).

Nem*_*emo 7

这或多或少有效:

#!/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)
Run Code Online (Sandbox Code Playgroud)

保存foo.py并尝试echo goodbye | ./foo.py

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


Leo*_*opd 5

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

你不能做的是管道输入和交互输入.如果您正在输入输入,则没有其他stdin可用raw_input的工作.唯一的stdin是来自文件的那个.

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

--input=file.txt
Run Code Online (Sandbox Code Playgroud)

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