Python argparse 帮助选项在使用 parse_known_args() 时不会显示所有参数

Python argparse help option won't display all of the arguments when using parse_known_args()

本质上,我有一个接受几个 optional/positional 参数的程序,但我想要一个可以单独使用的可选参数。我希望它的工作方式类似于“--version”选项的工作方式,如果给出该参数,则不需要位置参数并且代码运行。

我制作了几个测试文件来说明我的意思:

import argparse
import os,sys

def main():
    parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    
    parser.add_argument("--print-line", type=str, metavar="file", help="print the first line of a file")
    parser.add_argument("num", type=int, help="an important number")
    
    args = parser.parse_args()

    if args.print_line is not None:
        if not os.path.isfile(args.print_line):
            parser.error("file:%s not found" % args.print_line)
        with open(args.print_line, "r") as infile:
            print("First line:\n%s" % infile.readline().rstrip())
        return
    
    print("Important number: %i" % args.num)
    
    
if __name__ == "__main__":
    main()

帮助选项给出:

usage: notworks_goodhelp.py [-h] [--print-line file] num

positional arguments:
  num                an important number

optional arguments:
  -h, --help         show this help message and exit
  --print-line file  print the first line of a file (default: None)

太完美了!但是,如果我尝试使用可选参数,

$ python notworks_goodhelp.py --print-line file.txt 
usage: notworks_goodhelp.py [-h] [--print-line file] num
notworks_goodhelp.py: error: too few arguments

它不会工作,因为它缺少位置参数。

我使用 parse_known_args() 使脚本运行,但是帮助屏幕出现错误!如下所示:

import argparse
import os,sys

def main():
    parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    
    parser.add_argument("--print-line", type=str, metavar="file", help="print the first line of a file")
    args, leftovers = parser.parse_known_args()
    
    if args.print_line is not None:
        if not os.path.isfile(args.print_line):
            parser.error("file:%s not found" % args.print_line)
        with open(args.print_line, "r") as infile:
            print("First line:\n%s" % infile.readline().rstrip())
        return
    
    parser.add_argument("num", type=int, help="an important number")
    args = parser.parse_args(leftovers)
    
    print("Important number: %i" % args.num)
    
    
if __name__ == "__main__":
    main()

但是帮助屏幕是:

usage: works_nohelp.py [-h] [--print-line file]

optional arguments:
  -h, --help         show this help message and exit
  --print-line file  print the first line of a file (default: None)

缺少 'num' 位置参数!

有人知道解决这个问题的方法吗?

根据 chepner 的评论,我能够通过适当的操作和帮助屏幕让它在这个程序中工作。谢谢!

import argparse
import os,sys

class ExitOnAction(argparse.Action):
    def __init__(self, option_strings, dest, nargs=None, **kwargs):
        if nargs != 1 and nargs is not None:
            print("nargs: " + str(nargs))
            raise ValueError("nargs must be 1")
        super(ExitOnAction, self).__init__(option_strings, dest, **kwargs)
    
    def __call__(self, parser, namespace, values, option_string=None):
        setattr(namespace, self.dest, values)
        if not os.path.isfile(values):
            parser.error("file:%s not found" % values)
        with open(values, "r") as infile:
            print("First line:\n%s" % infile.readline().rstrip())
            sys.exit()
        
        

def main():
    parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    
    parser.add_argument("--print-line", action=ExitOnAction, type=str, metavar="file", help="print the first line of a file")
    parser.add_argument("num", type=int, help="an important number")
    
    print("Parsing args")
    args = parser.parse_args()
    print("Parsed args")
    '''
    if args.print_line is not None:
        if not os.path.isfile(args.print_line):
            parser.error("file:%s not found" % args.print_line)
        with open(args.print_line, "r") as infile:
            print("First line:\n%s" % infile.readline().rstrip())
        return
    '''
    print("Important number: %i" % args.num)
    
    
if __name__ == "__main__":
    main()