Argparse: Cara memasukkan nilai default di '--help'?

307

Misalkan saya memiliki potongan argparse berikut:

diags.cmdln_parser.add_argument( '--scan-time',
                     action  = 'store',
                     nargs   = '?',
                     type    = int,
                     default = 5,
                     help    = "Wait SCAN-TIME seconds between status checks.")

Saat ini, --helppengembalian:

usage: connection_check.py [-h]
                             [--version] [--scan-time [SCAN_TIME]]

          Test the reliability/uptime of a connection.



optional arguments:
-h, --help            show this help message and exit
--version             show program's version number and exit
--scan-time [SCAN_TIME]
                    Wait SCAN-TIME seconds between status checks.

Saya lebih suka sesuatu seperti:

--scan-time [SCAN_TIME]
                    Wait SCAN-TIME seconds between status checks.
                    (Default = 5)

Mengintip kode bantuan formatter mengungkapkan opsi terbatas. Apakah ada cara pintar argparseuntuk mencetak nilai default --scan-timedengan cara yang sama, atau haruskah saya hanya subkelas helppemformat?

JS.
sumber
5
Anda mungkin tertarik pada docopt . Saya tidak pernah melihat argparse lagi.
Paulo Scardine
14
@PauloScardine - Dibangun di dalam bahasa adalah manfaat utama bagi argparse.
jordanm
1
@ PauloScardine: Menarik pustaka non-standar ke proyek saya saat ini memang akan menyebalkan, tapi saya yakin seperti tampilan keluaran docopt. Terima kasih atas tipnya!
JS.
@ JS. Anda mengatakan "Menarik perpustakaan yang tidak standar ke proyek saya saat ini memang akan menyebalkan" Ada banyak perpustakaan yang sangat berguna di pypi. Dalam konteks saya, mudah untuk menarik di perpustakaan non-standar. Menyedihkan, jika sulit dalam konteks Anda.
guettli
3
@guettli: Proyek itu untuk proyek tertanam komersial. Instalasi Anda benar itu mudah. Mendapatkan persetujuan dari hukum perusahaan adalah mimpi buruk.
JS.

Jawaban:

447

Gunakan argparse.ArgumentDefaultsHelpFormatterformatter :

parser = argparse.ArgumentParser(
    # ... other options ...
    formatter_class=argparse.ArgumentDefaultsHelpFormatter)

Mengutip dokumentasi:

Kelas formatter lain yang tersedia,, ArgumentDefaultsHelpFormatterakan menambahkan informasi tentang nilai default setiap argumen.

Perhatikan bahwa ini hanya berlaku untuk argumen yang memiliki teks bantuan yang ditentukan ; tanpa helpnilai untuk sebuah argumen, tidak ada bantuan pesan untuk menambah informasi tentang nilai default untuk .

Output yang tepat untuk opsi waktu pindai Anda kemudian menjadi:

  --scan-time [SCAN_TIME]
                        Wait SCAN-TIME seconds between status checks.
                        (default: 5)
Martijn Pieters
sumber
12
Bisakah saya mengontrol bahwa hanya argumen dengan eksplisit yang default=menunjukkan nilai default? Karena saya tidak suka teks 'default: None'.
ziyuang
14
Anda dapat mengatur defaultke SUPPRESS: default=argparse.SUPPRESS. Perhatikan bahwa dalam kasus itu tidak ada atribut akan ditambahkan ke hasil namespace jika argumen yang dihilangkan, lihat itu defaultdokumentasi .
Martijn Pieters
4
Perhatikan bahwa Anda perlu menentukan ini untuk setiap subparser yang dibuat juga.
KomodoDave
1
Kemudian buat pertanyaan baru, termasuk contoh minimal yang dapat direproduksi yang menunjukkan masalahnya. Seperti yang saya katakan, ini berfungsi untuk saya dengan Python 2.7.
Martijn Pieters
3
@ David Saya mengalami masalah yang sama. Tambahkan helpargumen add_argumentdan itu akan berhasil.
Pablo Díaz Ogni
190

Tambahkan '%(default)s'ke parameter bantuan untuk mengontrol apa yang ditampilkan.

parser.add_argument("--type", default="toto", choices=["toto","titi"],
                              help = "type (default: %(default)s)")
polux.moon
sumber
9
Saya suka opsi ini karena saya sudah menggunakan format_class = argparse.RawTestHelpFormatter dan tidak merasa ingin berkeliaran dengan OOP.
mqsoh
23
Jangan lupa untuk memasukkan variabel 'ketik' dalam string pemformatan Anda - mis. '% (Default) s' untuk string, atau '% (default) d' untuk digit.
strongMA
1
Saya suka solusi ini jauh lebih baik, ini jauh lebih sederhana, dan saya tidak harus secara eksplisit menangani argumen tanpa nilai default.
void.pointer
@mqsoh multiple inheritance sebenarnya hanya berfungsi, tetapi sayangnya bukan API publik: stackoverflow.com/a/52025430/895245
Ciro Santilli 郝海东 冠状 病 六四 六四 事件 法轮功
1
Saya suka ini karena mengubah kelas formatter menambahkan banyak "(default: None)" di mana-mana yang mengacaukan bantuan.
6005
11

Kelas pembungkus

Ini adalah pendekatan yang paling andal dan KERING yang saya temukan sejauh ini untuk menunjukkan default dan menggunakan formatter lain seperti argparse.RawTextHelpFormatterpada saat yang sama:

#!/usr/bin/env python3

import argparse

class ArgumentParserWithDefaults(argparse.ArgumentParser):
    def add_argument(self, *args, help=None, default=None, **kwargs):
        if help is not None:
            kwargs['help'] = help
        if default is not None and args[0] != '-h':
            kwargs['default'] = default
            if help is not None:
                kwargs['help'] += ' Default: {}'.format(default)
        super().add_argument(*args, **kwargs)

parser = ArgumentParserWithDefaults(
    formatter_class=argparse.RawTextHelpFormatter
)
parser.add_argument('-a', default=13, help='''my help
for a''')
parser.add_argument('-b', default=42, help='''my help
for b''')
parser.add_argument('--no-default', help='''my help
for no-default''')
parser.add_argument('--no-help', default=101)

parser.print_help()
print()
print(parser.parse_args())

Keluaran:

usage: main.py [-h] [-a A] [-b B] [--no-default NO_DEFAULT]
               [--no-help NO_HELP]

optional arguments:
  -h, --help            show this help message and exit
  -a A                  my help
                        for a Default: 13
  -b B                  my help
                        for b Default: 42
  --no-default NO_DEFAULT
                        my help
                        for no-default
  --no-help NO_HELP

Namespace(a=13, b=42, no_default=None, no_help=101)

ArgumentDefaultsHelpFormatter+ RawTextHelpFormattermultiple inheritance

Beberapa warisan hanya berfungsi, tetapi sepertinya itu bukan API publik:

#!/usr/bin/env python3

import argparse

class RawTextArgumentDefaultsHelpFormatter(
        argparse.ArgumentDefaultsHelpFormatter,
        argparse.RawTextHelpFormatter
    ):
        pass

parser = argparse.ArgumentParser(
    formatter_class=RawTextArgumentDefaultsHelpFormatter
)
parser.add_argument('-a', default=13, help='''my help
for a''')
parser.add_argument('-b', default=42, help='''my help
for b''')
parser.print_help()

Keluaran:

usage: a.py [-h] [-a A] [-b B]

optional arguments:
  -h, --help  show this help message and exit
  -a A        my help
              for a (default: 13)
  -b B        my help
              for b (default: 42)

Ini hanya berfungsi karena seperti yang dapat kita lihat secara sepele dari sumber https://github.com/python/cpython/blob/v3.6.5/Lib/argparse.py#L648 bahwa:

  • RawTextHelpFormatter mengimplementasikan _split_lines
  • ArgumentDefaultsHelpFormatter mengimplementasikan _get_help_string

jadi kita bisa menebak bahwa mereka akan bekerja sama dengan baik.

Namun, ini sepertinya bukan API publik, dan juga tidak ada metode formatter_class, jadi saya tidak berpikir ada cara API publik untuk melakukannya saat ini. argparsedocstring mengatakan:

Semua kelas lain dalam modul ini dianggap sebagai detail implementasi. (Perhatikan juga bahwa HelpFormatter dan RawDescriptionHelpFormatter hanya dianggap publik sebagai nama objek - API objek formatter masih dianggap sebagai detail implementasi.)

Lihat juga: Kustomisasi pesan bantuan argparse

Diuji pada Python 3.6.5.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
sumber
1
Bagus ! Akhirnya memiliki dokumen yang diformat dan argumen default dicetak. Terima kasih
Sylvain