Python参数解析器,在h之前引发异常

2024-10-01 02:30:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我不知道为什么会这样。我的理解是用户至少有机会在执行默认操作之前使用-h。

import os, sys, argparse
class argument_parser():
  # call on all our file type parsers in the sequence_anlysis_method

    def __init__(self):
        self.db_directory = os.path.dirname(os.path.abspath(sys.argv[0]))

        """A customized argument parser that does a LOT of error checking"""
        self.parser = argparse.ArgumentParser(
            prog="igblast")

        general = self.parser.add_argument_group(
            title="\nGeneral Settings")

        general.add_argument(
            "-x", '--executable',
            default="/usr/bin/igblastn",
            type=self._check_if_executable_exists,
            help="The location of the executable, default is /usr/bin/igblastn")

        self.args = self.parser.parse_args()

    def _check_if_executable_exists(self,x_path):
        if not os.path.exists(x_path):
            msg = "path to executable {0} does not exist, use -h for help\n".format(x_path)
            raise argparse.ArgumentTypeError(msg)
        if not os.access(x_path, os.R_OK):
            msg1 = "executable {0} does have not permission to run\n".format(x_path)
            raise argparse.ArgumentTypeError(msg1)
        else:
            return x_path

if __name__ == '__main__':
    argument_class = argument_parser()

现在,如果/usr/bin/igblastn在那里,那么就可以了,但是如果不是的话,只要调用这个程序就会在self\u check_中引发异常,如果有可执行文件。

^{pr2}$

根据我的理解,用户总是有机会运行--help或-h,或者在采取任何导致此参数错误的操作之前。我对arg解析器的理解不清楚吗?


Tags: pathselfparserifbinosusrcheck
2条回答

您忘记在init__init__结束时运行^{}

class argument_parser(object):
    # call on all our file type parsers in the sequence_anlysis_method

    def __init__(self):
        self.db_directory = os.path.dirname(os.path.abspath(sys.argv[0]))

        """A customized argument parser that does a LOT of error checking"""
        self.parser = argparse.ArgumentParser(
            prog="igblast")

        general = self.parser.add_argument_group(
            title="\nGeneral Settings")

        general.add_argument(
            "-x", ' executable',
            default="/usr/bin/igblastn",
            type=self._check_if_executable_exists,
            help="The location of the executable, default is /usr/bin/igblastn")


        """ >>>>>>>>>>>>> add this line  <<<<<<<<<<< """
        self.parser.parse_args()

    def _check_if_executable_exists(self,x_path):
        if not os.path.exists(x_path):
            msg = "path to executable {0} does not exist, use -h for help\n".format(x_path)
            raise argparse.ArgumentTypeError(msg)
        if not os.access(x_path, os.R_OK):
            msg1 = "executable {0} does have not permission to run\n".format(x_path)
            raise argparse.ArgumentTypeError(msg1)
        else:
            return x_path

if __name__ == '__main__':
    argument_class = argument_parser()

在Python2.7.3中,parse_known_args(由parse_args调用)的早期,namespace中插入了默认值。在

    # add any action defaults that aren't present
    for action in self._actions:
        if action.dest is not SUPPRESS:
            if not hasattr(namespace, action.dest):
                if action.default is not SUPPRESS:
                    default = action.default
                    if isinstance(action.default, basestring):  # delayed in 3.3.1
                        default = self._get_value(action, default)
                    setattr(namespace, action.dest, default)

如果default是一个字符串,它将通过_get_value传递,该函数调用适当的type,在您的例子中是{}。这就产生了你所看到的错误。在

在3.3.1的新闻中https://docs.python.org/3.3/whatsnew/changelog.html

Issue #12776, issue #11839: Call argparse type function (specified by add_argument) only once. Before, the type function was called twice in the case where the default was specified and the argument was given as well. This was especially problematic for the FileType type, as a default file would always be opened, even if a file argument was specified on the command line.

通过此更改,_get_value调用被推迟到parse_known_args的末尾,并且只有在解析没有在那里放置其他值时才会调用它(需要默认值)。在

^{pr2}$

所以您的脚本在我的开发副本上按预期运行(使用'-h')。我不完全确定Python的哪个版本有这种更正。在

因此,在运行更新的Python版本之前,您有责任确保default是一个有效值。即使有了这个bug修复,在给add_argument()调用之前,最好确保默认值是有效的。无论何时处理,无效的默认值都会使用户感到困惑。在

相关问题 更多 >