Fully customized Python Help Usage

ε祈祈猫儿з 提交于 2019-12-11 02:08:25

问题


I'm trying to create a fully customized "help" usage with Python (which I plan to import into many programs that I want to have style consistency) but am having some trouble.

  1. I don't know why my description is ignoring newlines... tried "" and '',
  2. I can't get the ":" to occur after a /newline for the "...ARGS" lines, and obviously they look weird sitting on their own lines, and
  3. I have no idea how to add the newline at the end. Help please??

Here's a sample of what I am getting right now:

nameconstant version 1.0

USAGE:  myprog.py [constant text] <input.ext> <input.ext>

several lines of text describing my program.. because it will be necessary

___________________
COMPULSORY ARGS:
  input.ext
  output.ext

___________________
OPTIONAL ARGS:
  -v, --verbose  print debugging messages to terminal
  -h, --help

This is what I WANT it to look like:

nameconstant version 1.0

USAGE:  myprog.py [constant text] <input.ext> <input.ext>

several lines of text
describing my program..

because it will be necessary

___________________
COMPULSORY ARGS:

  input.ext
  output.ext

___________________
OPTIONAL ARGS:

  -v, --verbose      print debugging messages to terminal
  -h, --help
\n - not visible!

Here's the code I have working so far:

#!/usr/bin/env python
import argparse
import sys 
from os import path
version = "1.0"

prog = path.basename(sys.argv[0])

class USAGEformat(argparse.HelpFormatter):
        def add_usage(self, usage, actions, groups, prefix=None):
                if prefix is None:
                        prefix = 'nameconstant version '+ version+'\n\nUSAGE:  '+prog
                return super(USAGEformat, self).add_usage(
                      usage, actions, groups, prefix)

parser = argparse.ArgumentParser(add_help=False, formatter_class=USAGEformat, description='several lines of text\ndescribing my program..\n\nb
ecause it will be necessary', usage=' [optional args] <INPUT.ext> <OUTPUT.ext>')

parser._positionals.title = '___________________\nCOMPULSORY ARGS'
parser._optionals.title = '___________________\nOPTIONAL ARGS'

parser.add_argument('input', metavar="input.ext", type=argparse.FileType('rt'))
parser.add_argument('output', metavar="output.ext", type=argparse.FileType('wt'))
parser.add_argument('-v', '--verbose', action='store_true', default=False, help='print debugging messages to terminal')
parser.add_argument('-h', '--help', action='help', default=argparse.SUPPRESS)

What should I be doing differently or looking into next?? Thank you! Any help is greatly appreciated.. I am new to Python.


回答1:


import argparse
version = "1.0"

class USAGEformat(argparse.RawDescriptionHelpFormatter):
    def add_usage(self, usage, actions, groups, prefix=None):
        if prefix is None:
            prefix = 'nameconstant version '+ version+' USAGE:  '
            return super(USAGEformat, self).add_usage(
                usage, actions, groups, prefix)

parser = argparse.ArgumentParser(add_help=False, formatter_class=USAGEformat,
   description=\
'''several lines of text
describing my program..

because it will be necessary''')

gp1 = parser.add_argument_group('___________________\nCOMPULSORY ARGS')
gp1.add_argument('input', metavar="input.ext", type=argparse.FileType('rt'))
gp1.add_argument('output', metavar="output.ext", type=argparse.FileType('wt'))

gp2 = parser.add_argument_group('___________________\nOPTIONAL ARGS')
gp2.add_argument('-v', '--verbose', action='store_true', default=False,
      help='print debugging messages to terminal')
gp2.add_argument('-h', '--help', action='help', default=argparse.SUPPRESS)

parser.print_help()

produces

2156:~/mypy$ python stack47118098.py 
nameconstant version 1.0 USAGE:  stack47118098.py [-v] [-h]
                                                  input.ext output.ext

several lines of text
describing my program..

because it will be necessary

___________________
COMPULSORY ARGS:
  input.ext
  output.ext

___________________
OPTIONAL ARGS:
  -v, --verbose  print debugging messages to terminal
  -h, --help

RawDescriptionHelpFormatter preserves the formatting of the description.

I used the '''...''' for the description just to make the code look nicer; that's not important.

I substituted argument_groups for your renaming of the existing groups. Your way works fine, but I think mine is what the developers intended.

HelpFormatter formats the various pieces, with a generous use of \n between them, and then ends up stripping out duplicates (including the end). So we'd have to identify and modify the relevant method (format_help).

You've made some changes on the usage line since I started my answer.

I agree with the comment that required arguments are shown, by convention, without the [].

I got this usage because the line, with prefix, is too long. So it split it, and put the positionals on a second line, lined up with the optionals:

nameconstant version 1.0 USAGE:  stack47118098.py [-v] [-h]
                                                  input.ext output.ext

If I set

prefix = 'USAGE:  '

then usage is

USAGE:  stack47118098.py [-v] [-h] input.ext output.ext

We'd have to look at how it does wrapping and indenting to get the usage to your specs.

edit

In importing custom python modules.. why do only some elements carry over?

I explain that the help formatter is created fresh each time you ask for a help or usage. Defining the parser sets the formatter class, but does not create a formatter. That means that any global variables that the formatter class uses will get their values as runtime rather than setup.

For example, version is global (to the module). It is initially '1.0' and this is the value that appears in the usage. But if I add to the end of the above script:

version = '2.0'
parser.print_help()

the usage line changes to:

nameconstant version 2.0 USAGE:  stack47118098.py [-v] [-h]
                                                  input.ext output.ext

If I import this script with:

import stack47118098 as pp

print('===========')
print(pp.version)
print(pp.parser)
pp.parser.print_help()

pp.version = '3.0'
pp.parser.print_help()

the first help (after import) uses the '2.0' version that was in the file. But the second help uses the newly defined version.

To change something like the description of the parser, I have to use

pp.parser.description = 'New short description'

That is, I'm modifying an attribute of the existing object.



来源:https://stackoverflow.com/questions/47118098/fully-customized-python-help-usage

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!