2012-12-09 54 views
4

我想創建一個參數解析器有以下特徵:Python的ArgumentParser嵌套參數

./myapp [-a [-b BVAL] | -c]

換句話說,用戶只能在情況下提供論據-b BVAL如果他提供的參數-a

這是很容易創建的-a-c互斥組,但我無法弄清楚如何建立關係allow -b only if -a provided

回答

4

Docopt不只是因爲我想。了不起!

docopt('./myapp [-a [-b BVAL] | -c]') 
+1

這需要位於STANDARD LIBRARY中!您看到有人發佈了他們想要的用法文檔,然後無法爲他們創建用法文檔而出現了多少問題?這只是後退和錯誤。我們知道如何解釋用法文檔。爲什麼不能我們的代碼? Docopt的確如此。 –

2

這不是你在尋找什麼,但也許你會用什麼add_subparsers()doc)?

做這樣的事情:

import argparse 
parser = argparse.ArgumentParser() 
subparsers = parser.add_subparsers(help='sub-command help') 
a = subparsers.add_parser('a') 
c = subparsers.add_parser('c') 
a.add_argument('b') 
+0

是的,這聽起來很合理。讓我們等待是否有人能夠提供更接近我所尋找的解決方案。如果沒有更好的答案,我會和subparsers一起去,謝謝。 – kovpas

+1

Subparsers是我之前用於此目的的。 –

2

如果你不想使用subparsers,你可以處理你的論點使用parser.error重視自己。

import argparse 
parser = argparse.ArgumentParser() 
parser.add_argument('-a', dest='a', default='') # you can use other defaults surely 
parser.add_argument('-b', dest='b', default='') 
parser.add_argument('-c', dest='c', default='') 

args = parser.parse_args() 

if args.b and not args.a: 
    parser.error("Option 'b' can't be specified without 'a'") 

但還是考慮使用的情況下,你subparsers擴展可能的邏輯

5

你可以從ArgumentParser繼承添加一些自定義的功能。這裏我提出了一個例外,但是你可以修改這個來實現你想要的任何東西。只需更改on_dependency_error()方法以滿足您的需求。

from argparse import ArgumentParser 

class FancyParser(ArgumentParser): 
    # {'b': 'a'} Where b depends on a 
    dependencies = {} 

    def on_dependency_error(self, arg, depends_on): 
     raise FancyParser.DependencyError(
        'Argument %s depends on %s' % (arg, depends_on)) 

    def add_argument(self, *args, **kwargs): 
     depends_on = kwargs.get('depends_on') 
     if depends_on: 
      self.dependencies[kwargs.get('dest') or args[0]] = depends_on 
      del kwargs['depends_on'] 
     return super(FancyParser, self).add_argument(*args, **kwargs) 

    def parse_args(self, *args, **kwargs): 
     args = super(FancyParser, self).parse_args(*args, **kwargs) 
     for arg, depends_on in self.dependencies.iteritems(): 
      if getattr(args, arg) and not getattr(args, depends_on): 
       self.on_dependency_error(arg, depends_on) 
     return args 

    class DependencyError(Exception): 
     def __init__(self, *args, **kwargs): 
      return super(FancyParser.DependencyError, 
         self).__init__(*args, **kwargs) 

然後,您可以使用它像這樣 -

args = ['-a', '-b', 'BVAL', '-c'] 
parser = FancyParser() 
parser.add_argument('-a', dest='a', action='store_true') 
parser.add_argument('-b', dest='b', depends_on='a') 
parser.add_argument('-c', dest='c', action='store_true') 
try: 
    parser.parse_args(args) 
except FancyParser.DependencyError as e: 
    # Whatever here... 
    pass 
+0

太棒了!會試試看,謝謝。 – kovpas

+1

沒問題!只是更新了'parse_args()'方法以更好地測試依賴性。你會想要使用更新的代碼。謝謝! – pyrospade