Python argparse:命令行值未针对可选值初始化

Posted

技术标签:

【中文标题】Python argparse:命令行值未针对可选值初始化【英文标题】:Python argparse: command lines values are not initialised for optional values 【发布时间】:2021-06-26 20:36:56 【问题描述】:

我有以下要使用 argparse 解析的参数

input_dir(字符串:强制) output_dir(字符串:强制) file_path(字符串:强制) supported_file_extensions(逗号分隔字符串 - 可选) ignore_tests(布尔值 - 可选)

如果分别为supported_file_extensionsignore_tests 提供了逗号分隔的字符串和字符串,那么我希望将值设置为参数变量。我的设置如下

import sys

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument(
        'input_dir', type=str,
        help='Fully qualified directory for the input directory')
    parser.add_argument(
        'file_path', type=str,
        help='Fully  qualified path name for file')
    parser.add_argument(
       'output', type=str, help='Fully qualified output directory path')
    parser.add_argument(
        '-supported_file_extensions',nargs='?', type=str, default=None,
        help='optional comma separated file extensions'
    ) # Should default to False
    parser.add_argument(
        '-ignore_tests', nargs='?', type=bool, default=True
    ) # Should default to True if the argument is passed
    (arguments, _) = parser.parse_known_args(sys.argv[1:])
    print(arguments)

当我通过以下命令时

 python cloc.py -input_dir /myproject -file_path /myproject/.github/CODEOWNERS -output output.json --supported_file_extensions java,kt --ignore_tests False

我希望参数的值。--supported_file_extensions 等于 java,ktignore_tests 等于 False 但我得到以下值

Namespace(file_path='/myproject/.github/CODEOWNERS', ignore_tests=True, input_dir='/myproject', output='output.json', supported_file_extensions=None)

如果我没有在命令行参数中传递--ignored_tests,那么我希望文件默认为False。同样,当我传递--ignored_tests 时,我希望将参数设置为True

如果我传递--supported_file_extensions java,kt,那么我希望将参数设置为java,kt 作为字符串,而不是列表。

我尝试过,但没有成功。

    Python argparse: default value or specified value python argparse default value for optional argument Creating command lines with python (argparse)

更新 我将最后两个参数更新如下:

parser.add_argument(
        '-supported_file_extensions', type=str,
        help='optional comma separated file extensions'
    )
    parser.add_argument(
        '-ignore_tests', action='store_true',
        help='optional flag to ignore '
    )
    (arguments, _) = parser.parse_known_args(sys.argv[1:])
    print(arguments)

当我运行命令时

  python cloc.py -input_dir /myproject -file_path /myproject/.github/CODEOWNERS -output output.json --supported_file_extensions java,kt

输出如下

 Namespace(file_path='/myproject/.github/CODEOWNERS', ignore_tests=False, input_dir='/myproject', output='output.json', supported_file_extensions=None)

虽然ignore_tests 的值是正确的(默认为false),但supported_file_extensions 的值是None,这是不正确的,因为我已将java,kt 作为命令行参数传递。

当我通过时

 python cloc.py -input_dir /myproject -file_path /myproject/.github/CODEOWNERS -output output.json --supported_file_extensions java,kt --ignore_tests 

我得到以下输出

Namespace(file_path='/myproject/.github/CODEOWNERS', ignore_tests=False, input_dir='/myproject', output='output.json', supported_file_extensions=None)

【问题讨论】:

用户是否有某些原因必须通过TrueFalse?让他们通过开关,或者不通过,没有任何价值,这是一个好多更好的主意。 action='store_true' 操作将使其“正常工作”,无需定义 typedefaultnargs。您绝对不能使用bool 构造函数,因为bool("True")bool("False") 都为真(字符串上的bool 只有在字符串为空时才为假)。 '--ignore-test' 应该是action='store_true'。 (或“store_false”)不要使用type=bool。下定决心,标记的 st 3 args postional 是 '--input_dir' @ShadowRanger 没有要求。我想要一种根据命令行参数将 True 或 False 初始化为 ignore_tests 的方法。 当我在不带参数的 Linux 上运行代码时,它会显示带有 -supported_file_extensions 的帮助消息,它有一个 -,但你使用双 -- 运行它。如果我使用双 --supported_file_extensions 运行它,那么我会得到 None 但如果我使用单 -supported_file_extensions,那么它会给出正确的值。您只是以错误的方式使用-。您应该使用单 -output 和双 --supported_file_extensions 如果您定义add_argument('output'),那么它期望没有-output 的值。如果您使用单个 - 定义,例如 add_argument('-supported_file_extensions'),那么您也应该使用单个 - 来运行它,例如 -supported_file_extensions value。如果你想使用 double -- like --supported_file_extensions value 那么你应该定义 double -- like add_argument('--supported_file_extensions') 【参考方案1】:

你的论点不正确。您将参数注册到解析器为-ignore_tests,但在命令行上将其指定为--ignore_tests——注意前面的破折号的数量。您也不需要为位置参数指定-input_dir,它们什么都不做。

通常,上述两个问题都会导致您的脚本崩溃。它仍然运行的唯一原因是因为您使用的是parser.parse_known_args,它会忽略所有它不理解的参数——比如--ignore_tests-input_dir

你应该运行的命令是:

python cloc.py /myproject /myproject/.github/CODEOWNERS output.json -supported_file_extensions java,kt -ignore_tests False

此外,正如许多 cmets 所提到的,在注册参数时不要使用type=bool。相反,使用

parser.add_argument('-ignore_tests', action='store_true')

当存在-ignore_tests 时,这会将ignore_tests 设置为True,否则设置False — 无需在命令行上显式指定TrueFalse

【讨论】:

【参考方案2】:

我认为这是一个更好的定义:

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '--input_dir',
        help='Fully qualified directory for the input directory')
    parser.add_argument(
        '--file_path',
        help='Fully  qualified path name for file')
    parser.add_argument(
       '--output', help='Fully qualified output directory path')
    parser.add_argument(
        '--supported_file_extensions',
        help='optional comma separated file extensions'
    ) # only use ? if defining default and const
    parser.add_argument(
        '--ignore_tests', action='store_true'
    )
    (arguments, extras) = parser.parse_known_args()
    print(arguments)
    print(extras)

致电:

python cloc.py --input_dir /myproject --file_path /myproject/.github/CODEOWNERS --output output.json --supported_file_extensions java,kt

另一个版本:

如果 name == 'ma​​in': parser = argparse.ArgumentParser()

parser.add_argument(
    '--supported_file_extensions',
    help='optional comma separated file extensions')
parser.add_argument(
    '--ignore_tests', action='store_true')
parser.add_argument(
    'input_dir',
    help='Fully qualified directory for the input directory')
parser.add_argument(
    'file_path',
    help='Fully  qualified path name for file')
parser.add_argument(
    'output', help='Fully qualified output directory path')
(arguments, extras) = parser.parse_known_args()
print(arguments)
print(extras)

致电:

python cloc.py --ignore_tests /myproject /myproject/.github/CODEOWNERS output.json --supported_file_extensions java,kt

optionals (--) 可以按任何顺序排列,但positionals 必须按给定顺序排列。 positionals 没有标志或关键字。

【讨论】:

我希望能够传递命令行键。 command line keys 是什么意思?测试我的代码并查看Namespace。如果你想要不同的行为,你可能想直接解析sys.argv 我可能错了,但如果有人通过--key value,那么这意味着这些值是可选的,不是吗?我希望前三个是强制性的。 你可以设置required=True。或者只是给他们合理的默认值,所以你不在乎。或者让他们positionals(但是你不能在输入中使用标志词)。 您的建议对我有用。如果您可以使用required=True 更新您的答案,那么我可以接受。

以上是关于Python argparse:命令行值未针对可选值初始化的主要内容,如果未能解决你的问题,请参考以下文章

带有可选子命令的 argparse 未按预期工作

python argparse详解

python argparse - 要么两个可选参数,要么一个都没有

python命令行参数模块argparse

Python argparse:可以命名或定位的命令行参数

python 学习 argparse