2015-04-07 16 views
5

Podczas korzystania z argparse przekazanie --help do programu generuje tekst pomocy. Niestety, jest trudny do odczytania, ponieważ między opcjami nie ma pustych linii. Oto fragment, aby zilustrować:Python argparse: Wstaw pusty wiersz między pozycjami pomocy

optional arguments: 
    -h, --help   show this help message and exit 
    -u FILENAME, --up-sound FILENAME 
         The sound to play when the network comes up. Default: 
         "/path/to/some/sound/file.wav" 
    -d FILENAME, --down-sound FILENAME 
         The sound to play when the network goes down. Default: 
         "/path/to/some/other/sound/file.wav" 
    -p EXECUTABLE, --player EXECUTABLE 
         The program to use to play sounds. Default: "play" 
    -s, --silent   If specified, network_monitor.py will not play any 
         sounds. 
    -c, --no-clear-screen 
         If specified, screen will not be cleared (nor extra 
         blank lines added) before network_monitor.py runs. 
    --version    show program's version number and exit 

Zauważ, że w niektórych przypadkach, takich jak między -p i -s lub między -c i --version, trudno jest powiedzieć na pierwszy rzut oka, która pomaga tekst dotyczy która opcja. Pomiędzy wpisami powinien znajdować się pusty wiersz. Na przykład:

-p EXECUTABLE, --player EXECUTABLE 
         The program to use to play sounds. Default: "play" 

    -s, --silent   If specified, network_monitor.py will not play any 
         sounds. 

Jak mogę to zrobić? Severalother pytania zalecane przy użyciu argparse.RawTextHelpFormatter. Problem polega na tym, że jeśli go używam, muszę napisać własną logikę, aby zawinąć tekst pomocy, ponieważ formant pomocy w formacie tekstowym nie formatuje. Oczywistą odpowiedzią byłoby dołączenie '\n\n' na końcu tekstu pomocy i użycie domyślnego formatyzatora. Ale w niewytłumaczalny sposób nowe znaki zostają usunięte.

Jaka jest przyszłość? Używam Pythona 3.4.

Odpowiedz

6

Można utworzyć własny formater tekstu pomocy, który to robi. Zauważ, że wymaga to bardzo szczegółowej implementacji szczegółów implementacji argparse.HelpFormatter. Należy więc wziąć pod uwagę to ostrzeżenie zawarte w każdym opisie typu formatera pomocy:

Tylko nazwa tej klasy jest uznawana za publiczny interfejs API. Wszystkie metody dostarczone przez klasę są uważane za szczegóły implementacji.

Kiedy zignorować, tworząc własną pomocy formatowania, które dodaje pusty wiersz między wierszami jest bardzo prosta:

class BlankLinesHelpFormatter (argparse.HelpFormatter): 
    def _split_lines(self, text, width): 
     return super()._split_lines(text, width) + [''] 

I to wszystko. Teraz po utworzeniu obiektu ArgumentParser podczas przekazywania formatter_class=BlankLinesHelpFormatter do konstruktora, puste linie pojawią się między każdym argumentem w tekście pomocy.

+0

Właśnie tego szukałem. Dzięki. Jak sądzisz, jakie są szanse na to zerwanie w przyszłości? –

+0

The [plik źródłowy] (https://hg.python.org/cpython/log/default/Lib/argparse.py) nie był tak często dotykany w przeszłości, a większość z tych zmian nie miała wpływu na interfejs. Mimo ostrzeżenia powiedziałbym, że jesteś całkiem niezły od dłuższego czasu. Dodatkowo, po prostu wywołując metodę bazową, moje rozwiązanie nie zależy od dużej ilości i nie wymyśla ponownie żadnej logiki, która może przerwać w przyszłości. – poke

2

poke's podejście jest dobre. Zauważ, że RawTextHelpFormatter modyfikuje również tej metody, upraszczając go:

def _split_lines(self, text, width): 
    return text.splitlines() 

poke's metody mogą być manipulowane, aby dać Ci więcej kontroli

class BlankLinesHelpFormatter (argparse.HelpFormatter): 
    # add empty line if help ends with \n 
    def _split_lines(self, text, width): 
     lines = super()._split_lines(text, width) 
     if text.endswith('\n'): 
      lines += [''] 
     return lines 

z tym:

parser = argparse.ArgumentParser(description='A description', 
    formatter_class=BlankLinesHelpFormatter, 
    epilog='Epilog line', 
    ) 
parser.add_argument('-u', '--up-sound', metavar='FILENAME', 
    help='The sound to play when the network comes up. Default:"%(default)s"\n', 
    default="/path/to/some/sound/file.wav") 
# note \n in above help 
parser.add_argument('-d', '--down-sound', metavar='FILENAME', 
    help='The sound to play when the network goes down. Default:"%(default)s"', 
    default="/path/to/some/other/sound/file.wav") 
parser.add_argument('-s','--silent', action='store_true', 
    help='If specified, network_monitor.py will not play any sounds.') 
parser.add_argument('positional', nargs='*', help='positional argument') 
parser.print_help() 

wyświetlacze:

usage: stack29484443.py [-h] [-u FILENAME] [-d FILENAME] [-s] 
         [positional [positional ...]] 

A description 

positional arguments: 
    positional   positional argument 

optional arguments: 
    -h, --help   show this help message and exit 
    -u FILENAME, --up-sound FILENAME 
         The sound to play when the network comes up. 
         Default:"/path/to/some/sound/file.wav" 

    -d FILENAME, --down-sound FILENAME 
         The sound to play when the network goes down. 
         Default:"/path/to/some/other/sound/file.wav" 
    -s, --silent   If specified, network_monitor.py will not play any 
         sounds. 

Epilog line 

Dla porównania, wartość domyślna _split_lines jest:

def _split_lines(self, text, width): 
    text = self._whitespace_matcher.sub(' ', text).strip() 
    return _textwrap.wrap(text, width) 
    # self._whitespace_matcher = _re.compile(r'\s+') 

Usuwa końcowego \ N i redukuje wszystkie wewnętrzne odstępy jednego wykroju.