2012-07-12 19 views
12

निर्दिष्ट किया गया है मेरे अजगर स्क्रिप्ट में, मैं एक वैकल्पिक इनपुट पैरामीटर केवल जब एक और वैकल्पिक पैरामीटर निर्दिष्ट किया गया है उपयोग करने में सक्षम होना चाहता हूँ। उदाहरण:अजगर, argparse: इनपुट पैरामीटर सक्षम जब एक दूसरे से

$ python myScript.py --parameter1 value1 
$ python myScript.py --parameter1 value1 --parameter2 value2 

लेकिन नहीं:

$ python myScript.py --parameter2 value2 

मैं argparse के साथ ऐसा कैसे कर सकता हूँ?

धन्यवाद!

+1

क्या आप यदि 'myScript.py --parameter2 मान 2 --parameter1 value1' हो करना चाहते हैं? अगर आप इसे पारित करना चाहते हैं तो इससे निपटने के लिए यह एक बहुत मुश्किल मामला है। – mgilson

+1

http://bugs.python.org/issue11588 'mutually_inclusive_group' सुविधा के लिए एक बग अनुरोध है। यह इस मामले में काफी काम नहीं करेगा, क्योंकि '--parameter1'' --parameter2' के बिना हो सकता है। इस मुद्दे पर योगदान दें यदि आपके पास इस बारे में विचार हैं कि यह या संबंधित बाधाओं को कैसे कार्यान्वित किया जा सकता है। – hpaulj

उत्तर

10

एक कस्टम क्रिया का उपयोग करें:

import argparse 

foo_default=None  

class BarAction(argparse.Action): 
    def __call__(self,parser,namespace,values,option_string=None): 
     didfoo=getattr(namespace,'foo',foo_default) 
     if(didfoo == foo_default): 
      parser.error("foo before bar!") 
     else: 
      setattr(namespace,self.dest,values) 

parser=argparse.ArgumentParser() 
parser.add_argument('--foo',default=foo_default) 
parser.add_argument('--bar',action=BarAction,help="Only use this if --foo is set") 

#testing. 
print parser.parse_args('--foo baz'.split()) 
print parser.parse_args('--foo baz --bar cat'.split()) 
print parser.parse_args('--bar dog'.split()) 

यह भी थोड़ा आसान में किया जा सकता है अगर आप argparse के कुछ गैर-दस्तावेजी व्यवहार पर निर्भर के साथ ठीक कर रहे हैं जिस तरह से बनाए रखने के लिए:

import argparse 

parser=argparse.ArgumentParser() 
first_action=parser.add_argument('--foo',dest='cat',default=None) 

class BarAction(argparse.Action): 
    def __call__(self,parser,namespace,values,option_string=None): 
     didfoo=getattr(namespace,first_action.dest,first_action.default) 
     if(didfoo == first_action.default): 
      parser.error("foo before bar!") 
     else: 
      setattr(namespace,self.dest,values) 

parser.add_argument('--bar',action=BarAction, 
        help="Only use this if --foo is set") 

#testing. 
print parser.parse_args('--foo baz'.split()) 
print parser.parse_args('--foo baz --bar cat'.split()) 
print parser.parse_args('--bar dog'.split()) 

में इस उदाहरण में, हम foo के लिए डिफ़ॉल्ट मिलता है और यह कार्रवाई वस्तु add_argument द्वारा दिया (add_argument द्वारा दिया गया मान कहीं भी दर्ज नहीं किया है कि मैं पा सकते हैं) से गंतव्य है। यह अभी भी थोड़ा नाजुक है (यदि आप उदाहरण के लिए --foo तर्क में type= कीवर्ड निर्दिष्ट करना चाहते हैं)।

अंत में, आप को पार्स करने से पहले जांच कर सकते हैं sys.argv

import sys 
if ("--parameter2" in sys.argv) and ("--parameter1" not in sys.argv): 
    parser.error("parameter1 must be given if parameter2 is given") 

यह एक छोटे से अधिक मुश्किल हो जाता है --parameter1 भी --p1 द्वारा ट्रिगर किया जा सकता है अगर, लेकिन आप विचार मिलता है। फिर आप

if (set(sys.argv).intersection(('--p2',...)) and 
    not set(sys.argv).intersection(('--p1',...))) 

का लाभ यहां उपयोग कर सकते हैं कि किसी भी विशेष आदेश की आवश्यकता नहीं है। (--p2 कमांडलाइन पर --p1 पालन करने की आवश्यकता नहीं है)। और, इससे पहले के रूप में, आप कमांड स्ट्रिंग की सूची है कि अपने विशेष कार्रवाई option_strings विशेषता parser.add_argument(...) द्वारा लौटाए के माध्यम से ट्रिगर किया जाएगा प्राप्त कर सकते हैं। जैसे

import argparse 
import sys 
parser=argparse.ArgumentParser() 
action1=parser.add_argument('--foo') 
action2=parser.add_argument('--bar', 
          help="Only use this if --foo is set") 

argv=set(sys.argv) 
if ((argv & set(action2.option_strings)) and 
     not (argv & set(action1.option_strings))): 
       #^ set intersection 
    parser.error(' or '.join(action1.option_strings)+ 
        ' must be given with '+ 
        ' or '.join(action2.option_strings)) 
2

एक विचार मैन्युअल parser.parse_args() बुला के उत्पादन की जाँच करें और एक अपवाद को बढ़ाने या अन्यथा यदि --parameter2 प्रयोग किया जाता है लेकिन --parameter1 नहीं है विफल हो जाएगा।

आप custom action (थोड़ा नीचे स्क्रॉल) को --parameter2 पर सेट करने का प्रयास कर सकते हैं, तो --parameter1 नामस्थान के अंदर मौजूद है या नहीं।

अंत में, आप subparsers का उपयोग करने का प्रयास कर सकते हैं, हालांकि मुझे नहीं पता कि यह आपको --parameter1 के लिए कोई मान निर्दिष्ट करने देगा या नहीं।

2

आपको यह देखना होगा अगर --parameter1 पार्सर को --parameter2 जोड़ने से पहले दिया गया था parse_known_args() उपयोग कर सकते हैं।

import argparse 

parser = argparse.ArgumentParser() 
parser.add_argument('--parameter1', dest='p1') 
args = parser.parse_known_args()[0] 
if args.p1: 
    parser.add_argument('--parameter2', dest='p2') 
args = parser.parse_args() 

if args.p1: 
    print args.p1 
if args.p2: 
    print args.p2 

परिणाम:

$ python myScript.py --parameter1 a 
a 
$ python myScript.py --parameter1 a --parameter2 b 
a 
b 
$ python myScript.py --parameter2 b 
usage: myScript.py [-h] [--parameter1 P1] 
myScript.py: error: unrecognized arguments: --parameter2 b 
+2

'--help' हालांकि गलत होगा। – pmav99