2016-12-28 5 views
1

Ich schreibe einen Argument-Parser für ein Python-Modul mit verschiedenen Subparsern. Mein Ziel ist es, ein Argument zu haben, das Arguments Konstruktor gemeinsam genutzt werden, die mehrere Kinder weitergegeben wird:Python argparse: Name des Subparser-Programms in Hilfe-String

from argparse import ArgumentParser 
parser = ArgumentParser(prog = 'master') 
parser1 = ArgumentParser(help = None) 
parser1.add_argument('foo', type = int, help = 'Number of times to process %(prog)s') # Line of interest 
parser2 = ArgumentParser(help = None) 
parser2.add_argument('--bar', type = int, default = 0, help = 'Start at this number') 
parser3 = ArgumentParser(help = None) 
parser3.add_argument('--baz', type = str, default = 'DEFAULT', help = 'Init file with this text') 
subparsers = parser.add_subparsers() 
sp1 = subparsers.add_parser('prog1', parents = [parser1, parser2]) 
sp2 = subparsers.add_parser('prog2', parents = [parser1, parser3]) 
parser.parse_args('prog1 -h'.split()) 

Die gewünschte Ausgabe etwas wie

usage: master prog1 [-h] [--bar BAR] foo 

positional arguments: 
    foo   Number of times to process prog1 

optional arguments: 
    -h, --help  show this message and exit 
    --bar   Start at this number 

Wenn ich genau dieses Setup verwenden würde, bekomme ich master prog1 statt von prog1 in der Hilfsstring für foo. Was soll ich in der Zeile #Line of interest ändern, um das gewünschte Ergebnis zu erhalten?

Antwort

0

Dies ist keine direkte Antwort auf Ihre Frage, aber ich würde Click_ für das verwenden, was Sie versuchen zu tun.

Click_ in drei Punkten:

  1. beliebige Verschachtelung von Befehlen
  2. automatische Hilfeseite Generation
  3. verzögertes Laden von Subkommandos zur Laufzeit
0

Ich kann erklären, was los ist unterstützt, aber möglicherweise nicht in der Lage, eine Lösung anzubieten.

Die kurze Antwort ist, dass das sp1.prog sowohl in seinem usage Format als auch als %(prog)s Wert in den Hilfslinien verwendet wird. Und es ist mit dieser Linie usage konstruiert.

===============

sp1 = subparsers.add_parser('prog1', parents = [parser1, parser2]) 

schafft einen Parser, und fügt Argumente aus der parents. add_parser ist eine Methode der class _SubParsersAction (die Subparser-Action-Klasse). Und das prog Attribut für diesen Parser erstellt mit:

 if kwargs.get('prog') is None: 
     kwargs['prog'] = '%s %s' % (self._prog_prefix, name) 

Sie sollten dieses Attribut mit print(sp1.prog) sehen können (I ‚Master prog1‘ erwarten). Dies ist der Wert, der in der Zeile usage und in einer der Hilfszeilen mit %(prog)s verwendet wird.

subparsers._prog_prefix ist von parser.prog abgeleitet (Details siehe Code add_subparsers). Sie können aber auch einen prog Parameter angeben:

sp1 = subparsers.add_parser('prog1', parents = [parser1, parser2], prog='prog1') 

, dass die Zeichenfolge in der help Linie korrigieren sollte. Aber es wird auch die Zeichenfolge usage ändern.

Sie könnten auch die subparser geben eine explizite usage:

sp1 = subparsers.add_parser('prog1', parents = [parser1, parser2], prog='prog1', usage='master prog1 ...') 

Ohne auf die HelpFormatter zu tun Chirurgie glaube ich nicht, dass Sie prog in den Hilfslinien ändern können, ohne sie gleichzeitig auch in der Verwendung zu verändern.

Und so funktioniert die parents funktioniert können Sie die Helpline für prog1 foo nicht ändern, ohne auch für prog2 foo zu ändern. parents kopiert Aktionsobjekte als Referenz, sodass die beiden Unterparser das foo Action-Objekt gemeinsam nutzen.

Sie müssen zumindest die parents Ansatz für dieses Argument aufgeben und den Namen hartcodieren. Wenn Sie das Argument mehreren Unterparsern hinzufügen müssen, schreiben Sie eine kleine Dienstprogrammfunktion, um dies zu erleichtern. Der Mechanismus parents ist nur (in der Regel) eine Annehmlichkeit, etwas, das etwas Tipparbeit/Editieren spart.

===================

Dieses modifizierte Skript meine Punkte illustrieren

parser = ArgumentParser(prog = 'master') 

parser1 = ArgumentParser(add_help = False) 
fooarg=parser1.add_argument('foo', type = int, help = 'foo prog: %(prog)s') # Line of interest 
parser2 = ArgumentParser(add_help = False) 
parser2.add_argument('--bar', type = int, default = 0, help = 'Start at this number') 
parser3 = ArgumentParser(add_help = False) 
parser3.add_argument('--baz', type = str, default = 'DEFAULT', help = 'Init file with this text') 

subparsers = parser.add_subparsers(prog='subparsers') 
sp1 = subparsers.add_parser('prog1', parents = [parser1, parser2], prog='name1') 
sp2 = subparsers.add_parser('prog2', parents = [parser1, parser3]) 

#parser.print_help() 

# fooarg is an Action for both subparsers 
# print(fooarg.help) 
# fooarg.help = 'FOO HELP' 

print('==>sp1 prog:', sp1.prog) 
sp1.print_help() 
print('==>sp2 prog:', sp2.prog) 
sp2.print_help() 

sp1.prog = 'custom' 
sp1.print_help() 

# addition 
fooarg.default = 'default' 
fooarg.metavar = 'META' 
fooarg.help = 'prog: %(prog)s, dest=%(dest)s, nargs=%(nargs)s, type=%(type)s, default=%(default)s' 
sp1.print_help() 

Dieses letzte Stück eine Reihe von Action-Attribute ergänzt um die Hilfe. Aber prog ist der einzige, der von der parser kommt:

positional arguments: 
    META  prog: custom, dest=foo, nargs=None, type=int, default=default