2012-06-17 4 views
14

Ich schreibe ein Befehlszeilenprogramm mit Argparse und habe eine Reihe von sub_parsers (Unterbefehle) hinzugefügt. Im Hilfemenü erscheinen sie unter einer Gruppe namens "Befehle" und ich bekomme eine schöne Liste aller möglichen Optionen. Doch bevor diese Liste angezeigt wird, werden alle die gleichen Befehle erscheinen unter dem Gruppentitel in Klammern wie folgt:Argparse python, entfernen Subparser-Liste im Hilfe-Menü

Commands: 
    {foo, bar} 

    foo   - foo does foo 
    bar   - bar does bar 

ich die redundanten Einträge entfernen möchten, die in Klammern angezeigt. Es erscheint nur in dieser Gruppe, die mit sub_parsers gefüllt ist.

Mein Code sieht das zu handhaben wie folgt: (wobei Parser ist die ArgumentParser() Instanz)

subparsers = parser.add_subparsers(title="Commands") 

foo = subparsers.add_parser("foo", help="- foo does foo") 
bar = subparsers.add_parser("bar", help="- bar does bar") 

Ich habe bei den Attributen und Methoden meiner Befehle Aktionsgruppe sah und kann nicht scheinen zu Finde alles, was das für mich löst (zumindest aus dem, was ich verstehen kann). Ich bin mir nicht sicher, ob jemand anders damit umgegangen ist, ich weiß, dass es wahrscheinlich etwas unklar ist. Und noch einmal, ich versuche nur, die überflüssige Liste der Befehle zu finden, die in geschweiften Klammern erscheinen.

Antwort

11

Die "{foo, bar}" Teil ist das Argument 'metavar'. Ein Metavar ist, wie sich argparse auf erwartete Argumentwerte in den Zeichenfolgen usage und help bezieht. argparse behandelt Unterbefehle wie ein Argument mit mehreren Auswahlmöglichkeiten. Wenn Sie also kein Metavar angeben, ist der Standardwert die Liste der Auswahlmöglichkeiten (Unterbefehle) in geschweiften Klammern. Es lässt den Benutzer die möglichen Optionen für Unterbefehle wissen, aber da sie unten aufgeführt sind, ist es redundant und wenn Sie viele Unterbefehle haben, ist es hässlich.

Sie können ganz einfach mit Ihrem eigenen gewählt metavar ersetzen:

subparsers = parser.add_subparsers(title="Commands", metavar="<command>") 
+0

Perfect, genau was ich brauchte! Vielen Dank. –

+0

Es ist immer noch unmöglich, diesen Header vollständig zu entfernen. 'argparse' verlässt die leere Zeile. –

+1

@anatolytechtonik Siehe meinen Hack unten. – Naitree

3

Sie können Ihre Hilfemeldungsformatierung anpassen, indem Sie eine eigene Formatierungsklasse erstellen, die auf der Schnittstelle argparse.HelpFormatter basiert, und sie an den Konstruktor des Parsers übergeben, wobei das Argument formatter_class verwendet wird.

Weitere Details finden http://docs.python.org/dev/library/argparse.html#formatter-class

1

Nach dem Tauchen wirklich tief in argparse Quellcode habe ich konstruiert ein hacken die redundante {cmd1,...} Auswahlliste zu entfernen.

Der Hack implementiert einen benutzerdefinierten Hilfeformatierer, der die Formatierungsmethoden HelpFormatter im Umgang mit subparsers Aktion ändert. Insbesondere werden die Unterparser metavar und help Zeile in der Unterbefehlsargumentgruppe entfernt und die zusätzliche Einrückung dieser Unterbefehle entfernt.

Bitte vorsichtig verwenden.

Die Python 3-Version getestet, mit python3.6

from argparse import ArgumentParser, HelpFormatter, _SubParsersAction 

class NoSubparsersMetavarFormatter(HelpFormatter): 

    def _format_action(self, action): 
     result = super()._format_action(action) 
     if isinstance(action, _SubParsersAction): 
      # fix indentation on first line 
      return "%*s%s" % (self._current_indent, "", result.lstrip()) 
     return result 

    def _format_action_invocation(self, action): 
     if isinstance(action, _SubParsersAction): 
      # remove metavar and help line 
      return "" 
     return super()._format_action_invocation(action) 

    def _iter_indented_subactions(self, action): 
     if isinstance(action, _SubParsersAction): 
      try: 
       get_subactions = action._get_subactions 
      except AttributeError: 
       pass 
      else: 
       # remove indentation 
       yield from get_subactions() 
     else: 
      yield from super()._iter_indented_subactions(action) 

parser = ArgumentParser(formatter_class=NoSubparsersMetavarFormatter) 
subparsers = parser.add_subparsers(title="Commands") 

foo = subparsers.add_parser("foo", help="- foo does foo") 
bar = subparsers.add_parser("bar", help="- bar does bar") 

parser.parse_args(['-h']) 

Die Python 2-Version, getestet mit python2.7

from argparse import ArgumentParser, HelpFormatter, _SubParsersAction 

class NoSubparsersMetavarFormatter(HelpFormatter): 

    def _format_action(self, action): 
     result = super(NoSubparsersMetavarFormatter, 
         self)._format_action(action) 
     if isinstance(action, _SubParsersAction): 
      return "%*s%s" % (self._current_indent, "", result.lstrip()) 
     return result 

    def _format_action_invocation(self, action): 
     if isinstance(action, _SubParsersAction): 
      return "" 
     return super(NoSubparsersMetavarFormatter, 
        self)._format_action_invocation(action) 

    def _iter_indented_subactions(self, action): 
     if isinstance(action, _SubParsersAction): 
      try: 
       get_subactions = action._get_subactions 
      except AttributeError: 
       pass 
      else: 
       for subaction in get_subactions(): 
        yield subaction 
     else: 
      for subaction in super(NoSubparsersMetavarFormatter, 
            self)._iter_indented_subactions(action): 
       yield subaction 

parser = ArgumentParser(formatter_class=NoSubparsersMetavarFormatter) 
subparsers = parser.add_subparsers(title="Commands") 

foo = subparsers.add_parser("foo", help="- foo does foo") 
bar = subparsers.add_parser("bar", help="- bar does bar") 

parser.parse_args(['-h']) 

Beispielausgabe:

usage: a.py [-h] {foo,bar} ... 

optional arguments: 
    -h, --help show this help message and exit 

Commands: 
    foo   - foo does foo 
    bar   - bar does bar 
+1

Ich habe das etwas ähnlich - http://techtonik.rainforce.org/2016/11/help-formatting-problem-with-argparse.html - und ich denke, der richtige Weg für "Arsparse" Schmerz ist, alle seine Daten zu exportieren in einem Schritt und dann nur diese Daten formatieren, anstatt viele Hacks aufzurufen. –