2012-09-04 19 views
16

मैं पायथन के (2.7) argparse सुविधा का उपयोग कर रहा है और स्वचालित मदद यह विकल्प के आधार पर वर्णक्रमानुसार पैदा करता सॉर्ट करने के लिए करना चाहते हैं।argparse क्रमबद्ध मदद वर्णानुक्रम

डिफ़ॉल्ट सहायता प्रविष्टियों करके, जिस क्रम में वे जुड़ जाते हैं * में हल कर रहे हैं के रूप में:

p = argparse.ArgumentParser(description='Load duration curves and other plots') 
p.add_argument('--first', '-f', type=int, default=1, help='First Hour') 
p.add_argument('--dur', '-d', type=int, default=-1, help='Duration in Hours. Use -1 for all') 
p.add_argument('--title', '-t', help='Plot Title (for all plots), default=file name') 
p.add_argument('--interp', '-i', action="store_true", default=True, 
       help='Use linear interpolation for smoother curves') 
... 
args = p.parse_args() 

कौन सा जब python script -h के रूप में बुलाया का उत्पादन:

usage: script.py [-h] [--first FIRST] [--dur DUR] [--title TITLE] [--interp] 

Load duration curves and other plots 

optional arguments: 
    -h, --help   show this help message and exit 
    --first FIRST, -f FIRST 
         First Hour 
    --dur DUR, -d DUR  Duration in Hours. Use -1 for all 
    --title TITLE, -t TITLE 
         Plot Title (for all plots), default=file name 
    --interp, -i   Use linear interpolation for smoother curves 

यह स्वचालित रूप से वर्णानुक्रम उन्हें सुलझाने के लिए संभव है बजाय? यह डूर, पहला, एच, इंटरप, शीर्षक होगा।

* जाहिर है चारों ओर काम मैन्युअल p.add_argument का उपयोग करने में वर्णमाला के क्रम जोड़ा प्रविष्टियों को जोड़कर बनाए रखने के लिए है, लेकिन मैं ऐसा करने से बचने की कोशिश कर रहा हूँ।

+0

मुझे लगता है कि आप p.show_help या कुछ को हुक कर सकते हैं और मैन्युअल रूप से तर्क सूची को पार्स कर सकते हैं ... मैं देखूंगा कि मैं इस पर दस्तावेज़ ढूंढ सकता हूं ... –

उत्तर

16

आप एक कस्टम HelpFormatter class प्रदान करके ऐसा कर सकते हैं; जिनमें से आंतरिक आधिकारिक तौर पर अनियंत्रित हैं। इसका मतलब है आप अपने दम पर कर रहे हैं जब यह संस्करण के लिए अजगर संस्करण से संगतता के लिए आता है, लेकिन मैं इंटरफ़ेस काफी स्थिर लगता है:

from argparse import HelpFormatter 
from operator import attrgetter 

class SortingHelpFormatter(HelpFormatter): 
    def add_arguments(self, actions): 
     actions = sorted(actions, key=attrgetter('option_strings')) 
     super(SortingHelpFormatter, self).add_arguments(actions) 


p = argparse.ArgumentParser(... 
    formatter_class=SortingHelpFormatter, 
) 

यहाँ मैं प्रकार विकल्प तार (('--dur', '-d'), आदि) पर है, लेकिन आप कर सकते थे आप जिस चीज को सॉर्ट करना चाहते हैं उसके रूप में अपना चयन करें। यह सरल सॉर्टिंग विकल्प पिछले एकल-डैश विकल्प रखता है, जैसे -h विकल्प।

आउटपुट जो:

usage: [-h] [--first FIRST] [--dur DUR] [--title TITLE] [--interp] 

Load duration curves and other plots 

optional arguments: 
    --dur DUR, -d DUR  Duration in Hours. Use -1 for all 
    --first FIRST, -f FIRST 
         First Hour 
    --interp, -i   Use linear interpolation for smoother curves 
    --title TITLE, -t TITLE 
         Plot Title (for all plots), default=file name 
    -h, --help   show this help message and exit 
+0

'' सुपर (हेल्पफॉर्मेटर ''सुपर (सॉर्टिंगहेल्पफॉर्मेटर'' – jterrace

+0

कभी नहीं होना चाहिए, आपको मिल गया है :) – jterrace

+1

* निर्दोषता से सीट * –

1

जब आप ArgumentParser वर्ग बनाते हैं तो आप एक मदद फ़ॉर्मेटर में पारित कर सकते हैं: http://docs.python.org/library/argparse.html#formatter-class

तो जाहिरा तौर पर आपके द्वारा बताये गये formatters में से एक का उपयोग कर सकते हैं, लेकिन ओवरराइड और रिवर्स थोड़ा इंजीनियरिंग बिना उन्हें स्थान नहीं ले सकता:

>>> h = argparse.ArgumentDefaultsHelpFormatter 
>>> print h.__doc__ 
Help message formatter which adds default values to argument help. 

    Only the name of this class is considered a public API. All the methods 
    provided by the class are considered an implementation detail. 
+0

मैंने अक्सर सोचा है कि इनमें से अधिक का खुलासा होना चाहिए उपयोगकर्ता: -/(कुछ स्वरूपण प्रदान करने के अलावा और अनिवार्य रूप से उपयोगकर्ता को किसी भी तरह से उनके साथ गड़बड़ करने की अनुमति नहीं दे रहा है) - मुझे लगता है कि ऐसा इसलिए है क्योंकि कोड बहुत बदसूरत और लिखना मुश्किल है और Argparse devs नहीं चाहता था उस उपयोगकर्ता को उस पर अधीन करें। – mgilson

+1

जो विडंबनापूर्ण है, चूंकि 'Argparse' को कुरूपता और' optparse' codebase को विस्तारित करने में कठिनाई से प्रेरित किया गया था। – chepner

1

एक वैकल्पिक, निश्चित रूप से अधिक बदसूरत तरीका @MartijnPieters द्वारा प्रस्तावित की तुलना में यह करने के लिए:

p = argparse.ArgumentParser() 

#add arguements here 

for g in p._action_groups: 
    g._group_actions.sort(key=lambda x:x.dest) 

यह एक try में इस डाल करने के लिए अच्छा हो सकता है/except खंड के रूप में यह केवल मदद स्वरूपण है, इसलिए यह वास्तव में कार्यक्रम के निष्पादन के लिए कोई फर्क नहीं करना चाहिए अगर कोड के इस टुकड़े एक AttributeError या कुछ और पर विफल रहता है ...

+1

ऐसा कुछ है जिसे मैंने सोचा और काम करना प्रतीत होता था। लेकिन मैं आराम से यह सुझाव नहीं दे रहा था कि क्योंकि हम आसानी से नहीं बता सकते कि 'p._group_actions' के आदेश को बदलने वाले दुष्प्रभाव क्या हो सकते हैं। 'P._actions' में एक्शन ग्रुप के बारे में क्या? उन लोगों में ऑर्डर को किसी तरीके से जोड़ा जा सकता है और उन्हें भी बदलने की जरूरत है? तो उत्तर के लिए कोई उत्थान नहीं है, लेकिन कोड खोदने और मूल्य हैक करने के लिए एक मानसिक +1 ;-) –

+0

@ लुकासग्राफ - मैं ** गारंटी नहीं दूंगा ** यह समाधान चीजों को गड़बड़ नहीं करेगा, लेकिन मुझे लगता है * यह बहुत सुरक्षित है। सबकुछ उन शब्दकोशों का उपयोग करके पार्स किया जाता है जो वैसे भी अनियंत्रित हैं (ऐसा लगता है कि ऑर्डर केवल सहायता संदेश को स्वरूपित करने के उद्देश्य से रखा जाता है)। मैंने 'p._actions' को सॉर्ट करने का प्रयास किया, लेकिन ऐसा कोई प्रभाव नहीं प्रतीत होता है ... – mgilson

+0

यदि आप सभी को बदलना चाहते हैं तो सहायता लाइनों का क्रम है, फिर' _group_actions' सूचियों को सॉर्ट करना तार्किक है। – hpaulj

1

यह @ mgilson के जवाब के समान है। मैंने सोचा कि मैंने इसे पहले पोस्ट किया था, लेकिन स्पष्ट रूप से नहीं।

d = dict() 
d['--first'] = ('-f', "type=int", "default=1", "help='First Hour'") 
d['--dur'] = ('-d', type=int, default=-1, help='Duration in Hours. Use -1 for all') 
# etc 

for prim_option in sorted(d): 
    p.add_arguments(prim_option, *d[prim_option]) 

आप समायोजित कर सकते हैं वास्तव में क्या शब्दकोश में महत्वपूर्ण है, साथ ही sorted के तर्कों और add_arguments करने के लिए कॉल की सटीक संरचना के रूप में प्रयोग किया जाता है, वांछित छँटाई आदेश प्राप्त करने के लिए। यह argparse की सार्वजनिक रूप से प्रलेखित इंटरफ़ेस का पालन करता है, लेकिन अपने पार्सर परिभाषित करने की प्रक्रिया पर कोई परत जोड़ने है। (आपके दर्शन के आधार पर, पार्सर के कार्यान्वयन से विकल्पों के बारे में जानकारी को अलग करना एक अच्छी बात हो सकती है।)

1

मदद में बहस के क्रम parser.format_help विधि द्वारा निर्धारित किया जाता है:

Definition: parser.format_help(self) 
Source: 
    def format_help(self): 
     formatter = self._get_formatter() 
     ... 
     # positionals, optionals and user-defined groups 
     for action_group in self._action_groups: 
      formatter.start_section(action_group.title) 
      formatter.add_text(action_group.description) 
      formatter.add_arguments(action_group._group_actions) 
      formatter.end_section() 

help एक formatter वस्तु प्राप्त करने में कठिनाई, और फिर इसे करने के लिए 'वर्गों' जोड़कर बनाया जाता है। यहां यह _action_groups के माध्यम से लूप करता है, प्रत्येक को अपने स्वयं के अनुभाग में डालता है, और add_arguments विधि के साथ अपने क्रियाएं (तर्क) जोड़ता है। फॉर्मेटर अस्थायी है, केवल तार बनाने के लिए मौजूद है (आमतौर पर एकाधिक रेखाएं)।

कार्य समूहों में डिफ़ॉल्ट postionals और optionals, साथ ही उपयोगकर्ता द्वारा निर्मित कोई भी शामिल है। इन समूहों का उपयोग केवल मदद के लिए किया जाता है, न कि पार्सिंग के लिए। तो पार्सिंग को प्रभावित किए बिना action_group._group_actions सूची को फिर से व्यवस्थित किया जा सकता है। (पार्सर की अपनी कार्यवाही की सूची है, parser._actions)।

यह @ mgilson के अवलोकन की पुष्टि करता है कि p._actions सॉर्ट करने से सहायता प्रभावित नहीं होती है, लेकिन _group_actions सॉर्टिंग करता है।

छंटाई _actions को प्रभावित करेगा usage (चाहे मदद या स्टैंडअलोन का हिस्सा):

# usage 
    formatter.add_usage(self.usage, self._actions, 
         self._mutually_exclusive_groups) 

ध्यान दें कि action_groups उपयोग अनुभाग को पास नहीं कर रहे हैं। उपयोग अनुभाग अपने कार्यों को पुन: व्यवस्थित करता है, optionals पहले प्रदर्शित करता है, फिर positionals प्रदर्शित करता है।

add_argument चरण से पहले/उसके दौरान तर्कों को क्रमबद्ध करें यदि आप स्थिति के पार्सिंग ऑर्डर को नियंत्रित करना चाहते हैं, और उपयोग में उनके आदेश को नियंत्रित करना चाहते हैं।

यदि आप केवल सहायता समूहों में ऑर्डर नियंत्रित करना चाहते हैं, तो ._group_actions सूची में चीजों को फिर से व्यवस्थित करने के लिए स्वतंत्र महसूस करें, या तो फ़ॉर्मेटर को कॉल करने से पहले या उसके भीतर।

usage में कार्रवाइयों के क्रम को नियंत्रित करने के बारे में अन्य SO प्रश्न हैं। कुछ, उदाहरण के लिए, positionalsoptionals के बाद आदेश नहीं चाहते हैं।

मैं मानता हूं कि फॉर्मेटर वर्ग बोझिल है। लेकिन अधिकांश भाग के लिए, पार्सर वर्ग से अलग है। तो इसे पार्सिंग पर न्यूनतम प्रभाव के साथ फिर से लिखा जा सकता है। मौजूदा फॉर्मेटर सबक्लास बस निम्न स्तर के तरीकों को ट्विक करते हैं, जो लाइन रैपिंग को नियंत्रित करते हैं और लाइन बनाने में मदद करते हैं। पार्सर और फॉर्मेटर के बीच महत्वपूर्ण इंटरफ़ेस format_usage और format_help विधियां हैं, जो अपेक्षाकृत सरल और उच्चतम हैं।