Python argparse无法显示正确的帮助信息

5

我有一个使用 argparse 的 Python 脚本。在命令行中输入 python script_name.py -h 后,它会显示另一个命令的帮助信息,但代码仍然可以正常工作。脚本可以识别在其中定义的选项并正常运行,看起来脚本被某个东西打包了。我把 argparse 放到一个函数中,一切开始都工作得很好。我只是找不出是什么导致了帮助信息的改变。

以下是代码:

#!/usr/bin/env python

import os
import sys
import json
import logging
import argparse
import handlers


HZZ_DIR = os.path.dirname(os.path.abspath(__file__))
ROOT_DIR = os.path.dirname(os.path.dirname(HZZ_DIR))
logger = logging.getLogger('hzz_logger')
logger.setLevel(logging.DEBUG)
console = logging.StreamHandler()
console.setLevel(logging.INFO)
logger.addHandler(console)


def parse_args():
    arg_parser = argparse.ArgumentParser()
    arg_parser.add_argument('job', choices=['ws','lm','np'],
            help="ws: workspace; lm: limit; np: npranking")
    arg_parser.add_argument('-a', '--action', nargs=1,
            help="for Limit and NPranking: get/plot (limit/pull)")
    arg_parser.add_argument('-b', '--blinded', action='store_true',
            help="for Limit: true -- do expected only, false -- do observed as well.")
    arg_parser.add_argument('-v', '--version', nargs=1, type=int,
            help="input version")
    arg_parser.add_argument('-t', '--tag', nargs=1,
            help='workspace tag')
    arg_parser.add_argument('-m', '--mass', nargs='+', type=int,
            help='signal mass(es)')
    arg_parser.add_argument('-c', '--config', nargs=1,
            help='configure file')
    arg_parser.add_argument('-u', '--update', action='store_true',
            help="update default settings")
    args = arg_parser.parse_args()
    return args

def load_settings(args):
    pass


def run_job(settings):
    pass


def execute():
    args = parse_args()
    settings = load_settings(args)
    run_job(settings)


if __name__ == '__main__':
    execute()

这里粘贴了一条帮助信息,实际上是一个在此代码中未直接使用的命令的帮助信息。该命令的选项也可以被识别...

$ python hzz_handler.py -h
Usage: python [-l] [-b] [-n] [-q] [dir] [[file:]data.root] [file1.C ... fileN.C]
Options:
  -b : run in batch mode without graphics
  -x : exit on exception
  -n : do not execute logon and logoff macros as specified in .rootrc
  -q : exit after processing command line macro files
  -l : do not show splash screen
 dir : if dir is a valid directory cd to it before executing

  -?      : print usage
  -h      : print usage
  --help  : print usage
  -config : print ./configure options
  -memstat : run with memory usage monitoring

5
你看到的帮助信息似乎来自于 pyROOT,它有一个习惯就是接管 sys.argv。你的代码中有没有在任何地方导入过它? - dorian
3
是的,你说得对!pyROOT被导入到了handlers中。我该如何防止它接管sys.argv,或者至少有没有一种方法可以正确地打印出帮助信息?@dorian - Yicheng
argparse 这样的解析器可以读取 sys.argv 而不改变它。这意味着多个解析器可以读取相同的输入。-h 通常会显示其内容,然后退出,因此您将看到运行的第一个解析器的帮助信息。如果您的命令行包括两个解析器的内容,则可能需要使用 parse_known_args - hpaulj
2
根据这个链接,一个可能的解决方案似乎是这样的:import ROOT; ROOT.PyConfig.IgnoreCommandLineOptions = True - dorian
这是一个更好的解决方案!谢谢。@dorian - Yicheng
显示剩余3条评论
2个回答

1

哇,又是一个反Pythonic的ROOT之谜!您的问题和评论非常有帮助。为什么没有人发布带有ROOT.PyConfig.IgnoreCommandLineOptions = True的答案呢?

这里有一个原始的解决方法:

import argparse

# notice! ROOT takes over argv and prints its own help message when called from command line!
# instead I want the help message for my script
# therefore, check first if you are running from the command line
# and setup the argparser before ROOT cuts in

if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        formatter_class = argparse.RawDescriptionHelpFormatter,
        description = "my script",
        epilog = "Example:\n$ python my_script.py -h"
        )

    parser.add_argument("param", type=str, help="a parameter")
    parser.add_argument("-d", "--debug",    action='store_true', help="DEBUG level of logging")

    args = parser.parse_args()

    if args.debug:
        logging.basicConfig(level=logging.DEBUG)
    else:
        logging.basicConfig(level=logging.INFO)

    logging.debug("parsed args: %s" % repr(args))


import ROOT

...

if __name__ == '__main__':
    <do something with args>

0
总的来说,答案是在 argparse 之后始终调用 import ROOT。这样 ROOT 就不会接管 argparse 并打印我们想要的必需消息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接