2014-09-13 5 views
5

Mam skrypt w języku Python, który uruchamia dwa pod-komendy, które akceptują tę samą opcję, --config. Chciałbym stworzyć trzecie pod-polecenie, które kolejno może uruchamiać dwie pierwsze podkomendy.Funkcja rozwiązywania konfliktów argparse dla opcji w podkomendach przekształca argumenty ze słów kluczowych w argumenty pozycyjne

Używając argparse, utworzyłem cewkę dla każdego pod-polecenia, a także trzeci poziomy, którego rodzicami są dwa pod-polecenia. Aby wyjaśnić:

subcommand1 = subparsers.add_parser('subcommand1') 
subcommand1.add_argument('--config', help="The config") 

subcommand2 = subparsers.add_parser('subcommand2') 
subcommand2.add_argument('--config', help="The config") 

wrappercommand = subparsers.add_parser('wrappercommand', 
             parents=[subcommand1, subcommand2], 
             conflict_handler='resolve') 

Wszystko działa, gdy uruchamiam wrappercommand lub podkomendę2. Jednak subcommand1 przerw, z tym jako wyjście:

$ run_command.py subcommand1 --config path_to_config.ini 

usage: run_command.py subcommand1 config 

optional arguments: 
    help     show this help message and exit 
    config    The config 

Wygląda argparse okazało się argumentu słowa kluczowego („--config”) do położenia jednego („config”). Czy jest to oczekiwane zachowanie, gdy sprzeczne opcje są rozwiązywane przez argparse?

+0

Czy możesz opublikować pełny kod parsowania? Czy argument ma być "pomocnikiem"? – Forge

+0

To literówka - powinna to być "help =" Konfiguracja "". – hpaulj

Odpowiedz

3

Myślę, że popychasz tego handlarza konfliktami w niezamierzone i nieprzetestowane terytorium. Normalnie parents są samodzielnymi analizatorami, które nie są używane. Są tylko źródłem dla Actions. A konflikty dotyczące -h są obsługiwane za pomocą add_help=False.

drodze tle: z domyślnym conflict_handler (błąd) można dostać się komunikaty o błędach podczas tworzenia wrappercommand subparser:

argparse.ArgumentError: argument -h/--help: conflicting option string(s): -h, --help 

i po dodaniu jakiegoś add_help=False, można jeszcze dostać:

argparse.ArgumentError: argument --config: conflicting option string(s): --config 

Program obsługi konfliktów resolve zastępuje komunikaty o błędach jakąś "rozdzielczością". Poniższy skrypt pokazuje, co się dzieje.

Program obsługi resolve usunął option_strings dla akcji subcommand1, pozostawiając akcje w miejscu. W efekcie zmienia się obie na pozycje. A ponieważ help ma nargs=0, jest zawsze uruchamiany. Dlatego wyświetla się pomoc.

Intencją _handle_conflict_resolve jest usunięcie dowodów pierwszego argumentu, więc można dodać nowy argument. Działa to dobrze, gdy konflikt jest tworzony przez dwie komendy add_argument z tymi samymi ciągami opcji. Ale tutaj konflikt powstaje przez "kopiowanie" działań od 2 rodziców. Ale działania nadrzędne są kopiowane przez odniesienie, więc zmiany w "dziecku" kończą się na "rodzica".

Możliwe rozwiązania:

  • dodać argumenty wrappercommand bezpośrednio. Ten mechanizm parents po prostu dodaje argumenty od rodziców do dziecka. Nie "sekwencyjnie" uruchamia rodziców.

  • Napisz własną funkcję _handle_conflict_..., aby poprawnie rozwiązać konflikt.

  • Usunąć konflikty, aby można było korzystać z parents bez korzystania z obsługi resolve.


I złożyli raport o błędzie z tego przykładu http://bugs.python.org/issue22401:

parent1 = argparse.ArgumentParser(add_help=False) 
parent1.add_argument('--config') 
parent2 = argparse.ArgumentParser(add_help=False) 
parent2.add_argument('--config') 

parser = argparse.ArgumentParser(parents=[parent1,parent2], 
    conflict_handler='resolve') 

def foo(parser): 
    print [(id(a), a.dest, a.option_strings) for a in parser._actions] 

foo(parent1) 
foo(parent2) 
foo(parser) 

która produkuje:

[(3077384012L, 'config', [])] 
[(3076863628L, 'config', ['--config'])] 
[(3076864428L, 'help', ['-h', '--help']), (3076863628L, 'config', ['--config'])] 

Uwaga brakujące option_strings dla parent1 i dopasowanie id dla drugiego 2. parent1 nie może być ponownie użyty jako rodzic lub analizator składni.


argparse - Combining parent parser, subparsers and default values to kolejny przypadek, w którym działania kopiowanie dominującej przez odniesienie stwarza komplikacje (na zmianę ustawień domyślnych).

+0

Dziękuję, twoja odpowiedź jest poprawna we wszystkich punktach. Zamierzam dodać opcje bezpośrednio do akapitu bez użycia mechanizmu "rodziców". – toothgrinder