2011-06-10 44 views
4

是否可以在Python CLI腳本中結合管道輸入和TTY提示?例如,運行以下命令:Python中的管道和提示CLI腳本

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'環境變量不是一個可行的選擇)。

回答

5

這工作,或多或少:

#!/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

當然,/dev/tty只存在於Unix。如果你在沒有控制終端的過程中運行它,open()可能會失敗...

+0

我認爲這應該適用於一切(至少是常見的),但Windows。 Mac OS X有/ dev/tty對嗎? – yam655 2011-06-11 01:49:17

+0

@ yam655 - 我一直認爲OS X_is_ Unix就Python而言:-)。但你是對的。 – Nemo 2011-06-11 01:56:17

+0

謝謝!是的,這是我一直在尋找的解決方案。目前,我只支持Linux,它在Linux上運行良好。 – jorelli 2011-06-12 20:04:22

5

您可以檢測您的stdin是否來自管道,就像您使用sys.stdin.isatty一樣。你得到了EOF,因爲你讀取全部來自stdin.read()的輸入,然後嘗試使用raw_input()命令閱讀更多內容。

你不能做的是管道輸入和做交互輸入。如果你在輸入管道,沒有其他的stdinraw_input工作。唯一的stdin是來自該文件的。

你需要做的是提供了一個可選的方式有你的腳本的適當部分什麼從文件中讀取輸入,一個開關一樣

--input=file.txt 

然後提供其他部分的交互提示。

+0

其他解決方案:像'cat file - | | python mrprompt.py',如果你想在stdin中得到'file'的內容然後用戶輸入(但是在兩者之間不會有分隔符)。 – a3nm 2011-06-11 00:03:46

1

在同一程序中可以同時接受管道輸入和用戶輸入。

處理此問題的最簡單方法是使用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。