2009-03-30 11 views
31

Chcę program zrobić jedną rzecz, jeśli wykonywane tak:Jaki jest najlepszy sposób sprawdzenia, czy program Python ma cokolwiek do odczytania ze standardowego wejścia?

cat something | my_program.py 

i zrobić coś innego, jeśli uruchomić się ten

my_program.py 

Ale jeśli czytać ze standardowego wejścia, a następnie będzie czekać na użytkownika wejściowe, więc chcę sprawdzić, czy jest cokolwiek do przeczytania, zanim spróbuję odczytać ze standardowego wejścia.

+0

Co to znaczy „nie powinno być tak trudne, jak się wydaje” oznacza? Czy mógłbyś zaktualizować pytanie opisem swojego celu, dowolnego kodu, który wypróbowałeś do tej pory, który nie zadziałał, i czego oczekiwałeś? –

+0

dzięki Josh ... bardzo docenione. –

Odpowiedz

59

Jeśli chcesz wykryć, czy ktoś jest dane rurociągów do programu, lub działa on interaktywnie można użyć isatty zobaczyć jeśli stdin jest terminal:

$ python -c 'import sys; print sys.stdin.isatty()' 
True 
$ echo | python -c 'import sys; print sys.stdin.isatty()' 
False 
+0

Świetne rozwiązanie, dzięki! –

+0

Jeśli skrypt może być wykonywany zdalnie, czy to podejście isatty() nadal działa? Na przykład 'ssh somehost.com 'bash -c" python -c \ "importuj sys; print sys.stdin.isatty() \ "" 'zwraca' Fałsz " –

+0

Używając odpowiedzi @Trey Stout, skrypt zachowuje się zgodnie z oczekiwaniami przez ssh. 'ssh somehost.com 'bash -c" python -c \ "importuj sys; importuj zaznacz; r, w, x = select.select ([sys.stdin], [], [], 0); print (r) \ "" "Drukuje' [] '. To samo polecenie z potokiem to: 'ssh somehost.com 'bash -c" echo coś | python -c \ "import sys; importuj zaznacz; r, w, x = select.select ([sys.stdin], [], [], 0); print (r) \ "" "i który drukuje' [', tryb 'r' przy 0x7ff2aad250c0>] ' –

-2

Nie znam poleceń Pythona z mojej głowy, ale powinieneś być w stanie coś zrobić z ankietą lub wybrać, aby szukać danych gotowych do odczytu na standardowym wejściu.

To może być specyficzny dla systemu Unix i różni się w Windows Pythonie.

+0

Coś jak: select.select ([sys.stdin], [], [], 0) == ([sys.stdin], [], []) I, tak, to jest specyficzne dla Uniksa. –

2

Bad news. Z perspektywy wiersza poleceń w systemie Unix te dwie inwokacje twojego programu są identyczne.

Unix nie może ich łatwo odróżnić. To, o co prosisz, nie jest naprawdę sensowne i musisz wymyślić inny sposób korzystania z programu.

W przypadku, gdy nie znajduje się w potoku, co powinien przeczytać, jeśli nie czyta stdin?

Czy ma uruchomić GUI? Jeśli tak, możesz chcieć użyć opcji "-i" (--interactive), aby wskazać, że chcesz GUI, a nie czytać stdin.

Możesz czasami odróżnić rury od konsoli, ponieważ urządzenie konsoli to "/ dev/tty", ale nie jest to przenośne.

+0

+1: Każdy, kto kiedykolwiek walczył z aplikacją, która próbowała uroczych sztuczek, aby ominąć to doceń jakikolwiek dodatkowy wysiłek, który spędziłeś unikając takich uroczych sztuczek (lub przynajmniej czyniąc je wyraźnymi, jak sugeruje S.Lott). –

+0

Te inwokacje nie są identyczne, ponieważ "nieznany (google)" wskazał przy użyciu sys.stdin.isatty(). "isatty" jest przenośny pod Unix i jest używany na przykład w 'ls' (http://git.savannah.gnu.org/cgit/coreutils.git/tree/src/ls.c). Ale tak, to jest sztuczka, aby być ostrożnym w użyciu. –

+0

Inwokacje są identyczne - nie do odróżnienia. Urządzenia podłączone do standardowego wejścia są nieco inne. W zależności od/dev/tty jest możliwe, ale opcja jest banalna i oczywista. –

7

Chcesz wybrać moduł (man select na unixie) Pozwoli ci to przetestować czy jest coś czytelnego na stdin. Zauważ, że select nie działa w oknie z obiektami plików. Ale z pytaniem rury ładunkiem Jestem zakładając, że jesteś na os UNIX :)

http://docs.python.org/library/select.html

root::2832 jobs:0 [~] # cat stdin_test.py 
#!/usr/bin/env python 
import sys 
import select 

r, w, x = select.select([sys.stdin], [], [], 0) 
if r: 
    print "READABLES:", r 
else: 
    print "no pipe" 

root::2832 jobs:0 [~] # ./stdin_test.py 
no pipe 

root::2832 jobs:0 [~] # echo "foo" | ./stdin_test.py 
READABLES: [<open file '<stdin>', mode 'r' at 0xb7d79020>] 
+2

To nie mówi, czy wejście jest potokiem, tylko jeśli wejście jest dostępne. Rozważ: (sen 1 i echo "foo") | ./stdin_test.py Na mojej maszynie zgłasza "no pipe". –

+1

Interesująca uwaga. Myślę, że to dlatego, że selekcja nie blokuje. Kiedy zmieniam 0 na 5, twój przykład poprawnie pokazuje otwarty plik. Powinien naprawdę zostać wprowadzony w pętlę, która mogłaby cyklicznie do czasu, aż dane byłyby dostępne. Słuszna uwaga :) –

Powiązane problemy