Search code examples
python-3.xargparsepython-wheel

python Argpase is failing when code is created as a wheel file. But the same code is running fine on pycharm


Below is the code which is failing when uncommenting the last add_argument() i.e, --re_run_id. If it is commented, then the code is running fine. When the same code is converted to wheel the similar behavior is observed. Kindly help me a resolution.

import argparse

class ClsMain:
    def __init__(self):
        self.args = None

    def main(self):
        print("Control to function main")
        arg_parser = argparse.ArgumentParser()
        arg_parser.add_argument('--config_id',
                                type=int,
                                metavar='',
                                required=True,
                                help='ClientID/ConfigID for the job'
                                )
        arg_parser.add_argument('--execution_platform',
                                type=str,
                                metavar='',
                                required=True,
                                help='Databricks or others'
                                )
        arg_parser.add_argument('--file_system',
                                type=str,
                                metavar='',
                                required=True,
                                help='Filesystem to access, whether local, mount or ADLS'
                                )
        arg_parser.add_argument('--re_run_id',
                                type=str,
                                metavar='',
                                required=False,
                                help='ReRunID of the executed job'
                                )
        self.args = arg_parser.parse_args()
        print(arg_parser.print_help())


def prjmain():
    cmain = ClsMain()
    cmain.main()
    print("Main Completed")


prjmain()

Below is the error i am getting when executing from pycharm but it is executing fine when executed from command prompt.

Error:
+++++
self.args = arg_parser.parse_args()
  File "C:\Program Files\Python39\lib\argparse.py", line 1818, in parse_args
    args, argv = self.parse_known_args(args, namespace)
  File "C:\Program Files\Python39\lib\argparse.py", line 1851, in parse_known_args
    namespace, args = self._parse_known_args(args, namespace)
  File "C:\Program Files\Python39\lib\argparse.py", line 2088, in _parse_known_args
    self.error(_('the following arguments are required: %s') %
  File "C:\Program Files\Python39\lib\argparse.py", line 2573, in error
    self.print_usage(_sys.stderr)
  File "C:\Program Files\Python39\lib\argparse.py", line 2543, in print_usage
    self._print_message(self.format_usage(), file)
  File "C:\Program Files\Python39\lib\argparse.py", line 2509, in format_usage
    return formatter.format_help()
  File "C:\Program Files\Python39\lib\argparse.py", line 283, in format_help
    help = self._root_section.format_help()
  File "C:\Program Files\Python39\lib\argparse.py", line 214, in format_help
    item_help = join([func(*args) for func, args in self.items])
  File "C:\Program Files\Python39\lib\argparse.py", line 214, in <listcomp>
    item_help = join([func(*args) for func, args in self.items])
  File "C:\Program Files\Python39\lib\argparse.py", line 338, in _format_usage
    assert ' '.join(opt_parts) == opt_usage
AssertionError

Solution

  • I figured out the issue. help parameter in add_argument() takes a string, which tells you about the description of the parameter. If this string is long and spans over multiple lines, then the backend code in argparse.py module is breaking the line using the following code.

    # wrap the usage parts if it's too long
    text_width = self._width - self._current_indent
    if len(prefix) + len(usage) > text_width:
        # break usage into wrappable parts
        part_regexp = r'\(.*?\)+|\[.*?\]+|\S+'
        opt_usage = format(optionals, groups)
        pos_usage = format(positionals, groups)
        opt_parts = _re.findall(part_regexp, opt_usage)
        pos_parts = _re.findall(part_regexp, pos_usage)
        print ' '.join(opt_parts)
        print opt_usage
        assert ' '.join(opt_parts) == opt_usage
    

    The solution is to increase the width. use the following and the issue will be resolved.

    formatter = lambda prog: argparse.HelpFormatter(prog, width=500)
    arg_parser = argparse.ArgumentParser(formatter_class=formatter)
    

    If you don't use HelpFormatter, by default the width is -2. I initially used width as 100. part of my program started executing fine. I increased it to 500 and it is working fine now.