2011-01-22 15 views
17

यदि मेरे पास '-a', '-b', '-c', '-d' तर्क हैं, add_mutually_exclusive_group() फ़ंक्शन के साथ मेरे प्रोग्राम को केवल उनमें से एक का उपयोग करना होगा। क्या इसे गठबंधन करने का कोई तरीका है, ताकि प्रोग्राम केवल '-a 999 -b 999' या '-c 999 -d 999' स्वीकार करेगा?क्या Argparse (पायथन) तर्क के परस्पर अनन्य समूह का समर्थन करता है?

संपादित करें: अधिक स्पष्टता के लिए एक साधारण प्रोग्राम जोड़ने:

>>> parser = argparse.ArgumentParser() 
>>> group = parser.add_mutually_exclusive_group() 
>>> group.add_argument('-a') 
>>> group.add_argument('-b') 
>>> group.add_argument('-c') 
>>> group.add_argument('-d') 

तो केवल ./app.py -a | ./app.py -b | ./app.py -c | ./app.py -d कहा जा सकता है। क्या बहिष्कार समूह बहिष्करण समूह होना संभव है, ताकि केवल ./app.py -a .. -b .. | ./app.py -c .. -d .. को बुलाया जा सके?

उत्तर

6

संपादित करें: कभी भी ध्यान न दें। क्योंकि argparsegroup.add_argument का आह्वान करते समय एक विकल्प बनाने का भयानक विकल्प बनाता है। यह मेरी डिजाइन पसंद नहीं होगी। इस प्रकार

# exclusivegroups.py 
import conflictsparse 

parser = conflictsparse.ConflictsOptionParser() 
a_opt = parser.add_option('-a') 
b_opt = parser.add_option('-b') 
c_opt = parser.add_option('-c') 
d_opt = parser.add_option('-d') 

import itertools 
compatible_opts1 = (a_opt, b_opt) 
compatible_opts2 = (c_opt, d_opt) 
exclusives = itertools.product(compatible_opts1, compatible_opts2) 
for exclusive_grp in exclusives: 
    parser.register_conflict(exclusive_grp) 


opts, args = parser.parse_args() 
print "opts: ", opts 
print "args: ", args 

जब हम यह आह्वान, हम देख सकते हैं कि हम वांछित प्रभाव मिलता है: आप इस सुविधा के लिए बेताब हैं, तो आप ConflictsOptionParser साथ यह कर कोशिश कर सकते हैं।

$ python exclusivegroups.py -a 1 -b 2 
opts: {'a': '1', 'c': None, 'b': '2', 'd': None} 
args: [] 
$ python exclusivegroups.py -c 3 -d 2 
opts: {'a': None, 'c': '3', 'b': None, 'd': '2'} 
args: [] 
$ python exclusivegroups.py -a 1 -b 2 -c 3 
Usage: exclusivegroups.py [options] 

exclusivegroups.py: error: -b, -c are incompatible options. 

चेतावनी संदेश आपको सूचित नहीं है कि '-a' और '-b' दोनों '-c' के साथ असंगत हैं, फिर भी एक और अधिक उपयुक्त त्रुटि संदेश तैयार किया जा सकता है। नीचे पुराना, गलत जवाब।

पुराने संपादित करें:[यह संपादन गलत है, हालांकि नहीं यह सिर्फ एक आदर्श दुनिया हो सकता है अगर argparse इस तरह से काम किया है?] मेरे पिछले जवाब वास्तव में गलत थी, तो आप argparse के साथ ऐसा करने में सक्षम होना चाहिए प्रति पारस्परिक अनन्य विकल्पों में एक समूह निर्दिष्ट करके। हम प्रक्रिया को सामान्यीकृत करने के लिए itertools का भी उपयोग कर सकते हैं। और इसे बनाएं ताकि हमें सभी संयोजनों को स्पष्ट रूप से टाइप न करना पड़े:

import itertools 
compatible_opts1 = ('-a', '-b') 
compatible_opts2 = ('-c', '-d') 
exclusives = itertools.product(compatible_opts1, compatible_opts2) 
for exclusive_grp in exclusives: 
    group = parser.add_mutually_exclusive_group() 
    group.add_argument(exclusive_grp[0]) 
    group.add_argument(exclusive_grp[1]) 
+1

http://bugs.python.org/issue10984 में एक पैच है जो आपको एक से अधिक परस्पर अनन्य समूह में तर्क देने देता है। ऐसा करना एक आसान बदलाव है। ओवरलैपिंग समूहों के साथ सार्थक उपयोग का निर्माण करना अधिक शामिल है। – hpaulj

5

बस इस समस्या पर खुद को ठोकर खाई। Argparse दस्तावेज़ों के अपने पढ़ने से, Argparse के भीतर प्राप्त करने के लिए एक आसान तरीका प्रतीत नहीं होता है। मैंने parse_known_args का उपयोग करने पर विचार किया, लेकिन जल्द ही Argparse का एक विशेष उद्देश्य संस्करण लिखने की मात्रा ;-)

शायद एक बग रिपोर्ट क्रम में है। इस बीच, यदि आप अपने उपयोगकर्ता को एक छोटे से अतिरिक्त टाइपिंग करने के इच्छुक हैं, तो आप इसे उपसमूहों के साथ नकली बना सकते हैं (जैसे गिट और एसवीएन के तर्क कैसे काम करते हैं), उदा।

subparsers = parser.add_subparsers() 
    p_ab = subparsers.add_parser('ab') 
    p_ab.add_argument(...) 

    p_cd = subparsers.add_parser('cd') 
    p_cd.add_argument(...) 

आदर्श नहीं है, लेकिन कम से कम यह आपको बहुत अधिक बदसूरत हैकर के बिना argparse से अच्छा देता है। मैं स्विच के साथ दूर हो गया और बस उप-स्मारकों के साथ उप-स्पीकर संचालन का उपयोग कर समाप्त हो गया।

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