पायथन के अर्गपर्स में कई बार एक ही विकल्प का उपयोग करना


85

मैं एक स्क्रिप्ट लिखने की कोशिश कर रहा हूं जो कई इनपुट स्रोतों को स्वीकार करता है और प्रत्येक को कुछ करता है। कुछ इस तरह

./my_script.py \
    -i input1_url input1_name input1_other_var \
    -i input2_url input2_name input2_other_var \
    -i input3_url input3_name
# notice inputX_other_var is optional

लेकिन मैं यह पता नहीं लगा सकता कि इसका उपयोग कैसे किया जाए argparse। ऐसा लगता है कि इसे स्थापित किया गया है ताकि प्रत्येक विकल्प ध्वज का उपयोग केवल एक बार किया जा सके। मुझे पता है कि एक ही विकल्प ( nargs='*'या nargs='+') के साथ कई तर्कों को कैसे जोड़ा जाए , लेकिन यह अभी भी मुझे -iकई बार ध्वज का उपयोग नहीं करने देगा । मैं इसे कैसे पूरा कर सकता हूं?

बस स्पष्ट होने के लिए, मैं अंत में क्या चाहूंगा तार की सूची की एक सूची है। इसलिए

[["input1_url", "input1_name", "input1_other"],
 ["input2_url", "input2_name", "input2_other"],
 ["input3_url", "input3_name"]]

तो क्यों न एक ही विकल्प के साथ कई इनपुट स्रोत तर्कों को जोड़ा जाए?
टाइगरहावटी 3

क्योंकि कई इनपुट स्रोतों में से प्रत्येक के लिए कई स्ट्रिंग तर्क भी होने चाहिए। मैं इनपुट में से प्रत्येक के लिए -i ध्वज का उपयोग करना चाहता हूं, और प्रत्येक इनपुट में क्रमिक -i झंडे के बीच सभी तार शामिल होंगे। मैं चाहता हूं कि यह ffmpeg की तरह काम करे, जहां आप इनपुट्स को निर्दिष्ट करते हैं -i
John Allard

जवाबों:


97

यहां एक पार्सर है जो दोहराए गए 2 तर्क को वैकल्पिक रूप से संभालता है - जिसमें परिभाषित नाम हैं metavar:

parser=argparse.ArgumentParser()
parser.add_argument('-i','--input',action='append',nargs=2,
    metavar=('url','name'),help='help:')

In [295]: parser.print_help()
usage: ipython2.7 [-h] [-i url name]

optional arguments:
  -h, --help            show this help message and exit
  -i url name, --input url name
                        help:

In [296]: parser.parse_args('-i one two -i three four'.split())
Out[296]: Namespace(input=[['one', 'two'], ['three', 'four']])

यह 2 or 3 argumentमामले को संभालता नहीं है (हालांकि मैंने पायथन बग / मुद्दे के लिए कुछ समय पहले एक पैच लिखा था जो इस तरह की सीमा को संभालता है)।

कैसे एक अलग तर्क परिभाषा के साथ nargs=3और metavar=('url','name','other')?

टपल का metavarउपयोग nargs='+'और के साथ भी किया जा सकता है nargs='*'; 2 तार के रूप में [-u A [B ...]]या का उपयोग किया जाता है [-u [A [B ...]]]


1
वाह, बहुत अच्छा! मुझे पसंद है कि सहायता फ़ंक्शन कैसे दिखाता है कि बहु-भाग विकल्प के व्यक्तिगत घटक क्या दर्शाते हैं। मैं इस का उपयोग करेंगे!
जॉन अल्लार्ड

49

यह सरल है; बस दोनों action='append'और nargs='*'(या '+') जोड़ें ।

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-i', action='append', nargs='+')
args = parser.parse_args()

फिर जब आप इसे चलाते हैं, तो आप प्राप्त करते हैं

In [32]: run test.py -i input1_url input1_name input1_other_var -i input2_url i
...: nput2_name input2_other_var -i input3_url input3_name

In [33]: args.i
Out[33]:
[['input1_url', 'input1_name', 'input1_other_var'],
 ['input2_url', 'input2_name', 'input2_other_var'],
 ['input3_url', 'input3_name']]

2
धन्यवाद, वास्तव में मुझे क्या चाहिए! : D साइड नोट: एक संभावित डिफ़ॉल्ट प्रकार की सूची / सरणी होना आवश्यक है, या Argparse विफल हो जाएगा
टार्विन

22

-i3 तर्कों को स्वीकार करने और appendकार्रवाई का उपयोग करने के लिए कॉन्फ़िगर किया जाना चाहिए ।

>>> p = argparse.ArgumentParser()
>>> p.add_argument("-i", nargs=3, action='append')
_AppendAction(...)
>>> p.parse_args("-i a b c -i d e f -i g h i".split())
Namespace(i=[['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i']])

वैकल्पिक मान को संभालने के लिए, आप एक साधारण कस्टम प्रकार का उपयोग करने का प्रयास कर सकते हैं। इस मामले में, तर्क -iएक अल्पविराम-सीमांकित स्ट्रिंग है, जिसमें विभाजन की संख्या 2 तक सीमित है। आपको यह सुनिश्चित करने के लिए मूल्यों को पोस्ट-प्रोसेस करना होगा कि कम से कम दो मान निर्दिष्ट हैं।

>>> p.add_argument("-i", type=lambda x: x.split(",", 2), action='append')
>>> print p.parse_args("-i a,b,c -i d,e -i g,h,i,j".split())
Namespace(i=[['a', 'b', 'c'], ['d', 'e'], ['g', 'h', 'i,j']])

अधिक नियंत्रण के लिए, एक कस्टम क्रिया परिभाषित करें। यह एक बिल्ट-इन _AppendAction(द्वारा प्रयुक्त action='append') का विस्तार करता है, लेकिन बस दिए गए तर्कों की संख्या पर कुछ रेंज की जाँच करता है -i

class TwoOrThree(argparse._AppendAction):
    def __call__(self, parser, namespace, values, option_string=None):
        if not (2 <= len(values) <= 3):
            raise argparse.ArgumentError(self, "%s takes 2 or 3 values, %d given" % (option_string, len(values)))
        super(TwoOrThree, self).__call__(parser, namespace, values, option_string)

p.add_argument("-i", nargs='+', action=TwoOrThree)

1
प्रतिभाशाली! आपके सहयोग के लिए धन्यवाद।
जॉन एलार्ड

2
यह नहीं है काफी है कि तुम क्या चाहते हो; मैं चूक गया कि inputX_other_varवैकल्पिक है।
chepner

मैं सिर्फ इस तरह से टिप्पणी करने के लिए वापस आया, आपके तरीके को सभी संस्करणों की आवश्यकता है। हालांकि यह सही दिशा में है!
जॉन एलार्ड

1
ठीक है, एक वैकल्पिक 3 तर्क को संभालने के लिए कुछ विकल्पों के साथ अपडेट किया गया है।
चेपनर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.