संक्षिप्त उत्तर यह है कि parse_args
parse_known_args
का उपयोग करता है। यह विधि आपको --gold
जैसे अज्ञात तर्कों को संभालने देती है। नतीजतन, unknown arguments
त्रुटियों से पहले तर्क प्रकार त्रुटियां उठाई जाती हैं।
मैं एक समाधान है कि उपवर्गीकरण ArgumentParser
और एक विधि अपने बुला ढेर में गहरी बदलाव करना शामिल है जोड़ दिया है।
मैं parse_args
की रूपरेखा तैयार करने के रूप में अपने उदाहरण के लिए लागू की कोशिश करेंगे।
पहली चीज यह स्ट्रिंग को O
या A
के रूप में वर्गीकृत करती है। बस रखें, -
से शुरू होने वाले O
, अन्य A
हैं। यह परिभाषित तर्क के साथ O
लोगों से मेल खाता है।
आपके उदाहरण में, यह OAA
पाता है। रेगेक्स का प्रयोग nargs
तर्क द्वारा परिभाषित पैटर्न के खिलाफ इस स्ट्रिंग से मेल खाने के लिए किया जाता है। (यदि आवश्यक हो मैं और अधिक विस्तार में इस कदम की व्याख्या कर सकते)
--gold
से मेल नहीं खाता; किसी बिंदु पर (चाहे इस प्रारंभिक पाश या बाद में) यह extras
सूची में डाल दिया जाता है। (मैं विवरण के लिए कोड की जांच करूंगा)।
तार के माध्यम से 2 पाश के लिए यह बारी-बारी से postionals और optionals को संभालने के लिए कोशिश करता है।
5
से starttime
के साथ मिलान करने का प्रयास करते समय यह है कि आपकी एक्शन क्लास टाइप त्रुटि को बढ़ाती है, जो उपयोग को प्रिंट करने और बाहर निकलने के लिए प्रचारित करती है। क्योंकि --gold
परिभाषित नहीं है, 5
एक वैकल्पिक के तर्क के रूप में उपयोग नहीं कर रहा है।इस प्रकार यह पहली स्थितित्मक स्ट्रिंग के रूप में पार्स किया जाता है। (कुछ प्रकार के विकल्प 0 तर्क लेते हैं, इसलिए --...
के बाद यह कुछ भी नहीं मानता है)।
मुझे लगता है, कि 5
बिना, अंतिम स्ट्रिंग से मेल खाएगा। parse_known_args
extras
अवधि में --gold
साथ लौट आते हैं। parse_args
parse_known_args
का उपयोग करता है लेकिन एक त्रुटि को जन्म देती है जब extras
खाली नहीं है।
तो एक अर्थ में पार्सर दोनों त्रुटियों का पता करता है, लेकिन यह starttime
एक है कि त्रुटि संदेश से चलाता है। यह अपरिचित --gold
के बारे में शिकायत करने के अंत तक प्रतीक्षा करता है।
एक सामान्य दर्शन के रूप में, argparse
का पता लगाने और सभी त्रुटियों को पेश करने के लिए कोशिश नहीं करता। यह एक अंतिम व्यापक संदेश में मौजूद त्रुटियों की एक सूची एकत्र नहीं करता है।
मैं विवरण की जाँच करने के लिए कोड की समीक्षा करेंगे। मुझे नहीं लगता कि आप आसानी से बुनियादी पार्सिंग पैटर्न बदल सकते हैं। अगर मैं एक तरह से एक पहले unrecognized option
त्रुटि के लिए मजबूर करने के बारे में सोच है, मैं इस उत्तर संपादित करेंगे।
def _parse_optional(self, arg_string):
एक argv
स्ट्रिंग वर्गीकृत करने के लिए कोशिश करता है। यदि स्ट्रिंग positional
की तरह दिखती है तो यह None
लौटाती है। यह एक एक्शन option_string से मेल खाता है, यह एक टपल '(कार्रवाई, option_string, कोई नहीं) `मिलान कार्रवाई के साथ देता है। अंत में अगर मेल नहीं है, यह रिटर्न:
# it was meant to be an optional but there is no such option
# in this parser (though it might be a valid option in a subparser)
return None, arg_string, None
मुझे लगता है कि क्या अपने --gold
साथ होता है। कारण है कि यह अभी भी एक मान्य विकल्प हो सकता है ध्यान दें।
इस समारोह से
def _parse_known_args(self, arg_strings, namespace):
...
for i, arg_string in enumerate(arg_strings_iter):
....
option_tuple = self._parse_optional(arg_string)
if option_tuple is None:
pattern = 'A'
else:
option_string_indices[i] = option_tuple
pattern = 'O'
arg_string_pattern_parts.append(pattern)
...
# at the end
# return the updated namespace and the extra arguments
return namespace, extras
कहा जाता है का संग्रह है कि 'AOO'
पैटर्न, साथ ही इन tuples की एक सूची।
एक 2 पाश यह लेने वाली positionals और optionals के बीच alternates के दौरान
। समारोह है कि एक वैकल्पिक खपत है:
def consume_optional(start_index):
option_tuple = option_string_indices[start_index]
action, option_string, explicit_arg = option_tuple
if action is None:
extras.append(arg_strings[start_index])
...otherwise...
take_action(action, args, option_string)
जैसा कि मैंने पहले लिखा था, अपने --gold
extras
सूची में रखा जाता है, जबकि 5
तर्क positionals के रूप में पार्स किया जा सकता की सूची पर बनी हुई है।
namespace
और extras
आप के लिए parse_known_args
, उपयोगकर्ता, या parse_args
के माध्यम से पारित कर दिया गया है।
निश्चित रूप से आप ArgumentParser
उपclass कर सकते हैं और एक संशोधित _parse_optional
विधि परिभाषित कर सकते हैं। यह बजाय कि (None, arg_string, None)
टपल लौटने का एक त्रुटि बढ़ा सकता है।
import argparse
import datetime
class MyParser(argparse.ArgumentParser):
def _parse_optional(self, arg_string):
arg_tuple = super(MyParser, self)._parse_optional(arg_string)
if arg_tuple is None:
return arg_tuple # positional
else:
if arg_tuple[0] is not None:
return arg_tuple # valid optional
else:
msg = 'error: no such option: %s'%arg_string
self.error(msg)
def convertIsoTime(timestamp):
"""read ISO-8601 time-stamp using the AMS conventional format YYYY-MM-DDThh:mm:ssUTC"""
try:
return datetime.datetime.strptime(timestamp,"%Y-%m-%dT%H:%M:%SUTC")
except:
raise argparse.ArgumentTypeError("'{}' is not a valid ISO-8601 time-stamp".format(timestamp))
# parser = argparse.ArgumentParser()
parser = MyParser()
parser.add_argument('startTime', type=convertIsoTime)
parser.add_argument('--good', type=int,
help='foo')
args = parser.parse_args(['--good','5','2015-01-01T00:00:00UTC'])
print(args)
args = parser.parse_args(['--gold','5','2015-01-01T00:00:00UTC'])
1505:~/mypy$ python3 stack31317166.py
Namespace(good=5, startTime=datetime.datetime(2015, 1, 1, 0, 0))
usage: stack31317166.py [-h] [--good GOOD] startTime
stack31317166.py: error: error: no such option: --gold
उपवर्गीकरण प्रदान करने के लिए कस्टम क्रिया अच्छा argparse
(और अजगर) अभ्यास है पैदा करता है।
यदि आप पाइथन डेवलपर्स द्वारा इस मामले पर अधिक विचार करना चाहते हैं, तो bug/issue
लिखने पर विचार करें (पीईपी में अधिक विकसित औपचारिक विचारों के लिए है)। लेकिन argparse
कीड़े/पैच का काफी बैकलॉग है, और पीछे की संगतता के बारे में बहुत सावधानी बरतनी है।
http://bugs.python.org/issue?%40columns=id%2Cactivity%2Ctitle%2Ccreator%2Cassignee%2Cstatus%2Ctype&%40sort=-activity&%40filter=status&%40action=searchid&ignore=file%3Acontent&%40search_text=_parse_optional&submit=search&status=-1%2C1%2C2%2C3
बग/मुद्दों है कि संदर्भ _parse_optional
की एक सूची है। संभावित परिवर्तनों में शामिल हैं कि संदिग्ध विकल्प कैसे प्रबंधित किए जाते हैं। (मैं उन्हें यह देखने के लिए स्कैन करूंगा कि मैं कुछ भूल रहा हूं या नहीं। कुछ पैच मेरा हैं।) लेकिन super
का उपयोग करके, मेरा सुझाया गया परिवर्तन फ़ंक्शन के भीतर परिवर्तनों से प्रभावित नहीं होता है। यह केवल तभी प्रभावित होता है जब फ़ंक्शन को कॉल किया जाता है और यह क्या लौटाता है, जो होने की संभावना कम होती है। अपनी खुद की समस्या दर्ज करके, आप कम से कम डेवलपर्स को ध्यान दें कि कोई इस इंटरफ़ेस पर निर्भर करता है।
विस्तृत और उपयोगी स्पष्टीकरण के लिए धन्यवाद। मेरी एकमात्र चिंता यह होगी कि अगर Argparse अद्यतन किया जाता है तो यह तोड़ सकता है। मैं Argparse बैकलॉग के लिए एक अनुरोध जोड़ देंगे। –
मैंने मौजूदा मुद्दों पर एक नोट जोड़ा। – hpaulj