Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Custom help format for a choice argparse argument

59 views
Skip to first unread message

Ivan "Rambius" Ivanov

unread,
Jan 27, 2023, 3:31:56 PM1/27/23
to
Hello,

I am developing a script that accepts a time zone as an option. The
time zone can be any from pytz.all_timezones. I have

def main():
parser = argparse.ArgumentParser()
parser.add_argument("-z", "--zone", choices=pytz.all_timezones)
args = parser.parse_args()
print(args)
print(f"Specified timezone: {args.zone}")

It works, but when I run it with the -h option it dumps all entries in
pytz.all_timezones. I would like to modify the help format for just
-z|--zone option. I read the docs about HelpFormatter and argparse.py
and I ended up with

class CustomHelpFormatter(argparse.HelpFormatter):
def _metavar_formatter(self, action, default_metavar):
if action.dest == 'zone':
result = 'zone from pytz.all_timezones'
def format(tuple_size):
if isinstance(result, tuple):
return result
else:
return (result, ) * tuple_size
return format
else:
return super(CustomHelpFormatter,
self)._metavar_formatter(action, default_metavar)


def main():
parser = argparse.ArgumentParser(formatter_class=CustomHelpFormatter)
parser.add_argument("-z", "--zone", choices=pytz.all_timezones)
args = parser.parse_args()
print(args)
print(f"Specified timezone: {args.zone}")

This works, but is there a more elegant way to achieve it?

Regards
rambius

--
Tangra Mega Rock: http://www.radiotangra.com

Weatherby,Gerard

unread,
Jan 27, 2023, 4:23:19 PM1/27/23
to

Ivan "Rambius" Ivanov

unread,
Jan 27, 2023, 4:27:50 PM1/27/23
to
Hello,

On Fri, Jan 27, 2023 at 4:22 PM Weatherby,Gerard <gweat...@uchc.edu> wrote:
>
> Why not something like:
>
>
> parser.add_argument("-z", "--zone")
>
> args = parser.parse_args()
> if args.zone and args.zone not in ptyz.all_timezones:
>
> print(“Invalid timezone”,file=sys.stderr)
>
This is what I use now. I still wonder if I can mold HelpFormatter to
do what I want it to do.

Cameron Simpson

unread,
Jan 27, 2023, 4:42:58 PM1/27/23
to
On 27Jan2023 15:31, Ivan "Rambius" Ivanov <rambiuspa...@gmail.com> wrote:
>I am developing a script that accepts a time zone as an option. The
>time zone can be any from pytz.all_timezones. I have
>
>def main():
> parser = argparse.ArgumentParser()
> parser.add_argument("-z", "--zone", choices=pytz.all_timezones)
[...]
>
>It works, but when I run it with the -h option it dumps all entries in
>pytz.all_timezones.

What happens if you just presupply a `help=` parameter in
`add_argument`?

Cheers,
Cameron Simpson <c...@cskk.id.au>

Ivan "Rambius" Ivanov

unread,
Jan 27, 2023, 4:53:36 PM1/27/23
to
Hello Cameron,
I tried with def main():
parser = argparse.ArgumentParser()
parser.add_argument("-z", "--zone", choices=pytz.all_timezones,
help="a timezone from pytz.all_timezones")
args = parser.parse_args()
print(args)

-h still shows all the contents of pytz.all_timezones.

Regards
rambius

>
> Cheers,
> Cameron Simpson <c...@cskk.id.au>
> --
> https://mail.python.org/mailman/listinfo/python-list

Thomas Passin

unread,
Jan 27, 2023, 6:22:15 PM1/27/23
to
On 1/27/2023 4:53 PM, Ivan "Rambius" Ivanov wrote:
> Hello Cameron,
>
> On Fri, Jan 27, 2023 at 4:45 PM Cameron Simpson <c...@cskk.id.au> wrote:
>>
>> On 27Jan2023 15:31, Ivan "Rambius" Ivanov <rambiuspa...@gmail.com> wrote:
>>> I am developing a script that accepts a time zone as an option. The
>>> time zone can be any from pytz.all_timezones. I have
>>>
>>> def main():
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument("-z", "--zone", choices=pytz.all_timezones)
>> [...]
>>>
>>> It works, but when I run it with the -h option it dumps all entries in
>>> pytz.all_timezones.
>>
>> What happens if you just presupply a `help=` parameter in
>> `add_argument`?
>
> I tried with def main():
> parser = argparse.ArgumentParser()
> parser.add_argument("-z", "--zone", choices=pytz.all_timezones,
> help="a timezone from pytz.all_timezones")
> args = parser.parse_args()
> print(args)
>
> -h still shows all the contents of pytz.all_timezones.
>

Adding a few arguments makes it work (with the help of the argparse doc
page and Stack Overflow:

https://stackoverflow.com/questions/14950964/overriding-default-argparse-h-behaviour):

import argparse
import pytz

HELP ="""\nThis is the help message.
This is the second line of the help message."""

def main():
parser = argparse.ArgumentParser(add_help=False, usage = HELP)
parser.add_argument("-z", "--zone", choices=pytz.all_timezones,
help = argparse.SUPPRESS)
parser.add_argument('-h', '--h', action = 'help',
help = argparse.SUPPRESS)
args = parser.parse_args()
print(args)
print(f"Specified timezone: {args.zone}")


main()

Your help message will display after "usage", like this -

usage:
This is the help message.
This is the second line of the help message.

You would give up have argparse automatically list all the options, but
you can add add them manually to the HELP string.


Peter Otten

unread,
Jan 30, 2023, 5:20:49 PM1/30/23
to
On 27/01/2023 21:31, Ivan "Rambius" Ivanov wrote:
> Hello,
>
> I am developing a script that accepts a time zone as an option. The
> time zone can be any from pytz.all_timezones. I have
>
> def main():
> parser = argparse.ArgumentParser()
> parser.add_argument("-z", "--zone", choices=pytz.all_timezones)
> args = parser.parse_args()
> print(args)
> print(f"Specified timezone: {args.zone}")
>
> It works, but when I run it with the -h option it dumps all entries in
> pytz.all_timezones. I would like to modify the help format for just
> -z|--zone option. I read the docs about HelpFormatter and argparse.py
> and I ended up with
>
> class CustomHelpFormatter(argparse.HelpFormatter):
> def _metavar_formatter(self, action, default_metavar):
> if action.dest == 'zone':
> result = 'zone from pytz.all_timezones'
> def format(tuple_size):
> if isinstance(result, tuple):
> return result
> else:
> return (result, ) * tuple_size
> return format
> else:
> return super(CustomHelpFormatter,
> self)._metavar_formatter(action, default_metavar)
>
>
> def main():
> parser = argparse.ArgumentParser(formatter_class=CustomHelpFormatter)
> parser.add_argument("-z", "--zone", choices=pytz.all_timezones)
> args = parser.parse_args()
> print(args)
> print(f"Specified timezone: {args.zone}")
>
> This works, but is there a more elegant way to achieve it?

It may be sufficient to specify a metavar:

>>> import argparse
>>> p = argparse.ArgumentParser()
>>> p.add_argument("--foo", choices="alpha beta gamma".split(),
metavar="<any greek letter>")
[...]
>>> p.parse_args(["-h"])
usage: [-h] [--foo <any greek letter>]

optional arguments:
-h, --help show this help message and exit
--foo <any greek letter>

While that helps with --help it doesn't always prevent the choices list
from being spelt out:

>>> p.parse_args(["--foo", "whatever"])
usage: [-h] [--foo <any greek letter>]
: error: argument --foo: invalid choice: 'whatever' (choose from
'alpha', 'beta', 'gamma')

0 new messages