2009-11-16 13 views
49

मैंने एक कमांड लाइन उपयोगिता लिखी है जो कमांड लाइन पर दिए गए तर्कों को पार्स करने के लिए getopt का उपयोग करती है। मैं भी इस तरह के रूप में यह ग्रेप जैसे अन्य उपयोगिताओं में है, एक फ़ाइल नाम एक वैकल्पिक तर्क है आदि में कटौती के लिए तो, मैं इसे चाहते हैं निम्नलिखित उपयोगफ़ाइल से पढ़ें, या STDIN

tool -d character -f integer [filename] 

के लिए मैं निम्नलिखित कैसे लागू कर सकते हैं चाहते हैं ?

  • यदि फ़ाइल नाम दिया गया है, तो फ़ाइल से पढ़ें।
  • यदि कोई फ़ाइल नाम नहीं दिया गया है, तो STDIN से पढ़ें।
+2

यह भी देखें http://unix.stackexchange.com/questions/47098/how-do-i-make-python-programs-behave-like-proper-unix-tools/47543#47543 – magnetar

उत्तर

47

सरलतम रूप में:

import sys 
# parse command line 
if file_name_given: 
    inf = open(file_name_given) 
else: 
    inf = sys.stdin 

इस बिंदु पर आप inf का उपयोग फ़ाइल से पढ़ने का होगा। फ़ाइल नाम दिया गया था या नहीं, यह दिए गए फ़ाइल या stdin से पढ़ा जाएगा।

जब आप फ़ाइल को बंद करने की जरूरत है, तो आप ऐसा कर सकते हैं:

if inf is not sys.stdin: 
    inf.close() 

हालांकि, ज्यादातर मामलों में यह sys.stdin बंद करने के लिए हानिरहित हो सकता है अगर आप इसके साथ काम हो गया।

+0

कच्चे_इनपुट() और इनपुट() inf से पढ़ेगा? – thefourtheye

+0

@thefourtheye: हां, दोनों कार्य एक फ़ाइल या 'sys.stdin' से पढ़े जाएंगे। –

+2

मुझे इस समस्या को हल करने का एक और तरीका मिला, मैंने इसके बारे में यहां ब्लॉग किया http://dfourtheye.blogspot.in/2013/05/python-equivalent-of-cs-freopen.html और इस प्रश्न का उत्तर भी जोड़ा। – thefourtheye

61

fileinput मॉड्यूल तुम क्या चाहते हो सकता है - यह सोचते हैं गैर विकल्प तर्क तो args में हैं:

import fileinput 
for line in fileinput.input(args): 
    print line 

हैं args तो खाली है fileinput.input() stdin से पढ़ा जाएगा; अन्यथा यह प्रत्येक फ़ाइल से बदले में, पर्ल के while(<>) के समान तरीके से पढ़ता है।

+0

यह उतना ही अच्छा था एक उत्तर का, लेकिन काफी सामान्य नहीं है। यदि उपयुक्त हो तो अगली बार फ़ाइल इनपुट का उपयोग करना याद रखेगा। –

+0

यह 'args' के बिना भी काम करता है। – Gabriel

+0

ठीक है, लेकिन यदि आप 'गेटर्ग' (ओपी के रूप में) का उपयोग कर रहे हैं तो शायद आप 'sys.argv [1:] '(जो डिफ़ॉल्ट है) के बजाय बचे हुए तर्कों को पास करना चाहते हैं। – SimonJ

0

कुछ की तरह:

if input_from_file: 
    f = open(file_name, "rt") 
else: 
    f = sys.stdin 
inL = f.readline() 
while inL: 
    print inL.rstrip() 
    inL = f.readline() 
8

अजगर के with बयान का इस्तेमाल करते हैं, एक निम्नलिखित कोड का उपयोग कर सकते हैं:

import sys 
with open(sys.argv[1], 'r') if len(sys.argv) > 1 else sys.stdin as f: 
    # read data using f 
    # ...... 
+0

आपका समाधान 'sys.stdin' बंद कर देगा, इसलिए 'इनपुट' फ़ंक्शन कॉल 'with' कथन'' ValueError 'बढ़ाएगा। –

5

मैं का उपयोग करना पसंद "-" एक संकेत है कि आप पढ़ सकते हैं चाहिए के रूप में stdin से, यह अधिक स्पष्ट है:

import sys 
with open(sys.argv[1], 'r') if sys.argv[1] is not "-" else sys.stdin as f: 
    pass # do something here 
+2

आपका समाधान 'sys.stdin' बंद कर देगा, इसलिए 'इनपुट' फ़ंक्शन कॉल 'with' कथन' के बाद' ValueError 'बढ़ाएगा। –

+1

@TimofeyBondarev यह सच हो सकता है .. लेकिन अक्सर अक्सर एक स्क्रिप्ट में इनपुट का उपयोग किया जाता है। यह एक उपयोगी निर्माण है। – javadba

11

मुझे संदर्भ मैनेग का उपयोग करने के सामान्य मुहावरे पसंद हैं er, लेकिन (भी) तुच्छ समाधान sys.stdin बंद होने पर समाप्त होता है जब आप with कथन से बाहर होते हैं, जिसे मैं टालना चाहता हूं। ,

import sys 
import contextlib 

@contextlib.contextmanager 
def _smart_open(filename, mode='Ur'): 
    if filename == '-': 
     if mode is None or mode == '' or 'r' in mode: 
      fh = sys.stdin 
     else: 
      fh = sys.stdout 
    else: 
     fh = open(filename, mode) 
    try: 
     yield fh 
    finally: 
     if filename is not '-': 
      fh.close() 

if __name__ == '__main__': 
    args = sys.argv[1:] 
    if args == []: 
     args = ['-'] 
    for filearg in args: 
     with _smart_open(filearg) as handle: 
      do_stuff(handle) 

मैं तुम्हें something similar with os.dup() प्राप्त कर सकते थे लगता है लेकिन कोड मैं पकाया कि अधिक जटिल और अधिक जादुई साबित हुआ ऐसा करने के लिए, जबकि ऊपर कुछ हद तक है:

this answer से उधार, यहाँ एक समाधान नहीं है गुंजाइश लेकिन बहुत सीधा।

+0

बहुत बहुत धन्यवाद! यह वही है जो मैं देख रहा था। बहुत स्पष्ट और सीधे आगे समाधान। – edisonex

संबंधित मुद्दे