2011-12-15 13 views
19

मैं निम्नलिखित कोड (अजगर 2.7 का प्रयोग करके) है argparse वैकल्पिक subparser:(--version के लिए)

# shared command line options, like --version or --verbose 
parser_shared = argparse.ArgumentParser(add_help=False) 
parser_shared.add_argument('--version', action='store_true') 

# the main parser, inherits from `parser_shared` 
parser = argparse.ArgumentParser(description='main', parents=[parser_shared]) 

# several subcommands, which can't inherit from the main parser, since 
# it would expect subcommands ad infinitum 
subparsers = parser.add_subparsers('db', parents=[parser_shared]) 

... 

args = parser.parse_args() 

अब मैं चाहते हैं इस कार्यक्रम जैसे कॉल करने के लिए सक्षम होने के लिए --version सामान्य कार्यक्रम या कुछ subcommand के साथ जोड़ दिया साथ:

$ prog --version 
0.1 

$ prog db --version 
0.1 

असल में, मैं वैकल्पिक subparsers घोषित करने के लिए की जरूरत है। मुझे पता है कि यह really supported नहीं है, लेकिन क्या कोई कामकाज या विकल्प हैं?

संपादित करें: त्रुटि संदेश मैं हो रही है:

$ prog db --version 
# works fine 

$ prog --version 
usage: .... 
prog: error: too few arguments 

उत्तर

17
प्रलेखन के अनुसार

, action='version' साथ --version (और action='store_true' साथ नहीं) प्रिंट स्वचालित रूप से संस्करण संख्या:

parser.add_argument('--version', action='version', version='%(prog)s 2.0') 
2

हाँ, मैं बस svn चेक किया गया है, जिसे add_subparsers() documentation में किसी ऑब्जेक्ट उदाहरण के रूप में उपयोग किया जाता है, और यह केवल मुख्य आदेश पर '--version' का समर्थन करता है:

python zacharyyoung$ svn log --version 
Subcommand 'log' doesn't accept option '--version' 
Type 'svn help log' for usage. 

फिर भी:

# create common parser 
parent_parser = argparse.ArgumentParser('parent', add_help=False) 
parent_parser.add_argument('--version', action='version', version='%(prog)s 2.0') 

# create the top-level parser 
parser = argparse.ArgumentParser(parents=[parent_parser]) 
subparsers = parser.add_subparsers() 

# create the parser for the "foo" command 
parser_foo = subparsers.add_parser('foo', parents=[parent_parser]) 

कौन सा पैदावार:

python zacharyyoung$ ./arg-test.py --version 
arg-test.py 2.0 
python zacharyyoung$ ./arg-test.py foo --version 
arg-test.py foo 2.0 
1

हम wait for this feature वितरित किए जाने वाले करते हैं, हम कोड इस तरह उपयोग कर सकते हैं:

# Make sure that main is the default sub-parser 
if '-h' not in sys.argv and '--help' not in sys.argv: 
    if len(sys.argv) < 2: 
     sys.argv.append('main') 
    if sys.argv[1] not in ('main', 'test'): 
     sys.argv = [sys.argv[0], 'main'] + sys.argv[1:] 
+0

ध्यान दें कि हम इस बुनियादी सुविधा 2009 – yac

+0

के बाद से मैं अंतर्निहित तर्क पार्सर के बजाय docopt का उपयोग प्रारंभ कर के लिए प्रतीक्षा करें। यह "क्रियाओं", उर्फ ​​"क्रियाओं" के साथ या बिना मिश्रित उपयोग का समर्थन करता है। http://docopt.org/ –

7

Fwiw, मैं में भाग यह भी, और subparsers का उपयोग न करके इसे "हल" कर दिया (मैं पहले से ही अपना खुद का था प्रिंटिंग सहायता के लिए सिस्टम, इसलिए वहां कुछ भी खोना नहीं था)।

parser.add_argument("command", nargs="?", 
        help="name of command to execute") 

args, subcommand_args = parser.parse_known_args() 

... और फिर subcommand अपनी ही पार्सर (एक subparser के समान) है जो केवल subcommand_args पर चल रही है बनाता है:

इसके बजाय, मैं यह कर।

3

जैसा कि http://bugs.python.org/issue9253 (argparse: वैकल्पिक उपपरर्स) में चर्चा की गई है, पाइथन 3.3 के रूप में, उपपरक्षक अब वैकल्पिक हैं। यह आवश्यक तर्कों के लिए parse_args की जांच में बदलाव का एक अनपेक्षित परिणाम था।

मुझे एक धुंध मिली जो पिछले (आवश्यक उपपरर्स) व्यवहार को पुनर्स्थापित करता है, subparsers क्रिया के required विशेषता को स्पष्ट रूप से सेट करता है।

parser = ArgumentParser(prog='test') 
subparsers = parser.add_subparsers() 
subparsers.required = True # the fudge 
subparsers.dest = 'command' 
subparser = subparsers.add_parser("foo", help="run foo") 
parser.parse_args() 

अधिक जानकारी के लिए यह समस्या देखें। मैं उम्मीद करता हूं कि यदि यह समस्या ठीक तरह से पैच हो जाती है, तो उप-पाठकों को डिफ़ॉल्ट रूप से आवश्यक होगा, विशेषता False पर सेट करने के लिए किसी प्रकार के विकल्प के साथ। लेकिन argparse पैच का एक बड़ा बैकलॉग है।

0

हालांकि @ eumiro का उत्तर --version विकल्प को संबोधित करता है, यह केवल ऐसा ही कर सकता है क्योंकि यह ऑप्टपर के लिए एक विशेष मामला है।के सामान्य आमंत्रण देने के लिए:

prog 
prog --verbose 
prog --verbose main 
prog --verbose db 

और prog --version काम prog --verbose main (और prog main --verbose) के रूप में ही आप Argumentparser के लिए एक विधि जोड़ सकते हैं और फोन कि डिफ़ॉल्ट subparser के नाम के साथ, बस parse_args() लागू करने से पहले कर सकते हैं:

import argparse 
import sys 

def set_default_subparser(self, name, args=None): 
    """default subparser selection. Call after setup, just before parse_args() 
    name: is the name of the subparser to call by default 
    args: if set is the argument list handed to parse_args() 

    , tested with 2.7, 3.2, 3.3, 3.4 
    it works with 2.6 assuming argparse is installed 
    """ 
    subparser_found = False 
    for arg in sys.argv[1:]: 
     if arg in ['-h', '--help']: # global help if no subparser 
      break 
    else: 
     for x in self._subparsers._actions: 
      if not isinstance(x, argparse._SubParsersAction): 
       continue 
      for sp_name in x._name_parser_map.keys(): 
       if sp_name in sys.argv[1:]: 
        subparser_found = True 
     if not subparser_found: 
      # insert default in first position, this implies no 
      # global options without a sub_parsers specified 
      if args is None: 
       sys.argv.insert(1, name) 
      else: 
       args.insert(0, name) 

argparse.ArgumentParser.set_default_subparser = set_default_subparser 

def do_main(args): 
    print 'main verbose', args.verbose 

def do_db(args): 
    print 'db verbose:', args.verbose 

parser = argparse.ArgumentParser() 
parser.add_argument('--verbose', action='store_true') 
parser.add_argument('--version', action='version', version='%(prog)s 2.0') 
subparsers = parser.add_subparsers() 
sp = subparsers.add_parser('main') 
sp.set_defaults(func=do_main) 
sp.add_argument('--verbose', action='store_true') 
sp = subparsers.add_parser('db') 
sp.set_defaults(func=do_db) 

parser.set_default_subparser('main') 
args = parser.parse_args() 

if hasattr(args, 'func'): 
    args.func(args) 

set_default_subparser() विधि ruamel.std.argparse पैकेज का हिस्सा है।

4

ऐसा लगता है कि यह एक वैकल्पिक उपपरक्षक का मूल विचार लागू करता है। हम मानक तर्कों का विश्लेषण करते हैं जो सभी उप-सामग्रियों पर लागू होते हैं। फिर, अगर कुछ भी बचा है, तो हम बाकी पर पार्सर का आह्वान करते हैं। प्राथमिक तर्क उप-आदेश के माता-पिता हैं, इसलिए -h सही तरीके से दिखाई देता है। यदि कोई उप-आदेश मौजूद नहीं है तो मैं एक इंटरैक्टिव प्रॉम्प्ट दर्ज करने की योजना बना रहा हूं।

import argparse 

p1 = argparse.ArgumentParser(add_help = False)  
p1.add_argument(‘–flag1′) 

p2 = argparse.ArgumentParser(parents = [ p1 ]) 
s = p2.add_subparsers() 
p = s.add_parser(‘group’) 
p.set_defaults(group=True) 

(init_ns, remaining) = p1.parse_known_args() 

if remaining: 
    p2.parse_args(args = remaining, namespace=init_ns) 
else: 
    print(‘Enter interactive loop’) 

print(init_ns)