2012-10-30 49 views
4

sys.stdin.readline()在返回之前等待EOF(或換行),所以如果我有控制檯輸入,readline()等待用戶輸入。相反,如果沒有任何可處理的內容,我想打印幫助並退出,並等待用戶輸入。如何避免使用python處理空標準輸入?

原因: 我正在尋找寫命令行行爲類似於grep的python程序。

測試用例:

無輸入並沒有什麼管道,打印幫助

$ argparse.py 
argparse.py - prints arguments 

echo $?   # UNIX 
echo %ERRORLEVEL% # WINDOWS 
2 

命令行參數解析

$ argparse.py a b c 
0 a 
1 b 
2 c 

接受管道命令

$ ls | argparse.py 
0 argparse.py 
1 aFile.txt 

parseargs.py清單:

# $Id: parseargs.py 

import sys 
import argparse 

# Tried these too: 
# import fileinput - blocks on no input 
# import subprocess - requires calling program to be known 

def usage(): 
    sys.stderr.write("{} - prints arguments".fomrat(sys.argv[0]) 
    sys.stderr.flush() 
    sys.exit(2) 

def print_me(count, msg): 
    print '{}: {:>18} {}'.format(count, msg.strip(), map(ord,msg)) 

if __name__ == '__main__': 
    USE_BUFFERED_INPUT = False 
    # Case 1: Command line arguments 
    if len(sys.argv) > 1: 
     for i, arg in enumerate(sys.argv[1:]): 
      print_me(i, arg) 
    elif USE_BUFFERED_INPUT: # Note: Do not use processing buffered inputs 
     for i, arg in enumerate(sys.stdin): 
      print_me(i, arg) 
    else: 
     i=0 
     ##### Need to deterime if the sys.stdin is empty. 
     ##### if READLINE_EMPTY: 
     #####  usage() 
     while True: 
      arg = sys.stdin.readline() #Blocks if no input 
      if not arg: 
       break 
      print_me(i, arg) 
      i += 1 
    sys.exit(0) 
+1

我想'Fasle'應該是'FALSE': - ),'argparse.py'應該是'parseargs.py' – mgilson

+0

elif False應該做什麼?這是故意的嗎? – SilentGhost

+0

我猜這只是造成它的一面旗幟......他可以改變,以迅速管理行爲... –

回答

5

grep可以工作,因爲它有一個非可選參數:模式。例如

$ grep < /dev/zero 
Usage: grep [OPTION]... PATTERN [FILE]... 
Try `grep --help' for more information. 

即使stdin上有無限的輸入,grep沒有得到所需的參數,因此抱怨。

如果您只想使用可選參數並在stdin是終端時出錯,請查看file.isatty()

+0

謝謝!這從命令行工作(在eclipse IDE中它總是返回false)。 –

+0

'not sys.stdin.isatty()'比我上面的fstat東西更容易檢查 –

+1

附錄:我調用了sys.stdin.isatty()來確定結果是否來自管道命令。 –

2
import sys,os 
print os.fstat(sys.stdin.fileno()).st_size > 0 

調用腳本

c:\py_exp>peek_stdin.py < peek_stdin.py 
True 

c:\py_exp>peek_stdin.py 
False 
+1

感謝fstat的想法,但管道是在輸入前創建的,所以dir | peek_stdin.py(或linux中的ls | peek_fstat.py)返回false。我可能會仔細看看fstat。 –

+0

啊你是對的:)我不知道那個... –

0

您可能要檢查getopt模塊。基本例如:

import getopt 
import sys 

def main(argv): 
    try: 
     opts, args = getopt.getopt(argv, "has:f:") # "has:f:" are the arguments 
    except getopt.GetoptError: 
     print "print usage()" 
     sys.exit(1) 
    if not opts and not args: 
     print "print usage()" 
     sys.exit(1) 

    print "args passed", opts, args 
if __name__ == "__main__": 
    main(sys.argv[1:]) 


~> python blabla.py 
print usage() 
~> python blabla.py -a arg 
args passed [('-a', '')] ['arg'] 
~> python blabla.py -b as ----> this fails because -b is not defined for getopt at second parameter 
print usage() 

這個怎麼樣:

#!/usr/bin/env python 
import getopt 
import sys 
import select 


def main(argv): 
    try: 
     opts, args = getopt.getopt(argv, "has:f:") # "has:f:" are the arguments 
    except getopt.GetoptError: 
     print "print usage()" 
     sys.exit(1) 
    if not opts and not args: 
     a, b, c = select.select([sys.stdin], [], [], 0.2) 
     if a: 
      itera = iter(a[0].readline, "") 
      for line in itera: 
       data = line.strip() 
       print data 
     else: 
      print "print usage()" 

    print "args passed", opts, args 
if __name__ == "__main__": 
    main(sys.argv[1:]) 

select.select有助於檢查是否有數據來

:~> ./hebele.py 
print usage() 
args passed [] [] 

:~> ping www.google.com | ./hebele.py 
PING www.google.com (173.194.67.105) 56(84) bytes of data. 
64 bytes from blabla (173.194.67.105): icmp_seq=1 ttl=48 time=16.7 ms 
64 bytes from blabla (173.194.67.105): icmp_seq=2 ttl=48 time=17.1 ms 
64 bytes from blabla (173.194.67.105): icmp_seq=3 ttl=48 time=17.1 ms 
^CTraceback (most recent call last): 
    File "./hebele.py", line 25, in <module> 
    main(sys.argv[1:]) 
    File "./hebele.py", line 17, in main 
    for line in itera: 
KeyboardInterrupt 
:~> ls | ./hebele.py 
Aptana_Studio_3 
Desktop 
... 
workspace 
args passed [] [] 

:~> ./hebele.py -a bla 
args passed [('-a', '')] ['bla'] 
:~> ./hebele.py sdfsdf sadf sdf 
args passed [] ['sdfsdf', 'sadf', 'sdf'] 
+0

這與他的問題確實沒有任何關係......(除非getopt允許管道輸入或重定向輸入(我不認爲它確實......但它可能) –

+0

我沒有意識到'pipe'ing是問題,直到我我會搜索它是否支持管道 – savruk

+0

@Joran你對第二種解決方案有什麼看法?它與getopt'實際上沒有關係,但它仍然可以工作 – savruk

相關問題