【问题标题】:Conditional choices of an argument based on a preceding argument基于前一个参数的参数的条件选择
【发布时间】:2021-10-03 17:03:53
【问题描述】:

我想创建一个脚本,它需要使用两个参数:

  • 目录路径,
  • files -- directory_path 参数下的文件列表

我写过类似的东西:

#!/usr/bin/python3

import argparse
import os

import argcomplete

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument("directory_path",
                        help="a path to some directory",
                        nargs=1)

    # conditional choices of an argument
    conditional_choices = [os.listdir(parser.parse_known_args()[0].directory_path[0])]
    parser.add_argument("files",
                        metavar="FILES",
                        nargs='+',
                        choices=conditional_choices)

    argcomplete.autocomplete(parser)
    args = parser.parse_args()

    print("directory_path {}".format(args.directory_path))
    print("files {}".format(args.files))

所以 files 参数取决于 directory_path 参数。

使用:Python3.8

问题

对于上述 sn-p,files 参数的 bash-completion(由 register-python-argcomplete3 构建)不起作用。 如果我在有效命令(带有路径和文件)之后按回车键,则会出现错误

error: argument FILES: invalid choice: ...

【问题讨论】:

  • 在没有完成者的情况下可以工作吗?虽然我很理解argparse,但我还没有对完成者做任何事情。
  • 错误信息是否包含问题字符串和有效选项?如果是这样,它们是你所期望的吗?
  • [os.listdir(...] 中的 [] 过多。错误消息应列出 invalid choice: 'xxx' (choose from '.hdfview2.11', ... 不带 []
  • 不,没有完成者也是行不通的。我已经记录了它在我的计算机上的工作方式asciinema.org/a/QD9t1fA584QwzBkaowZDwM64F [如果 asciinema 链接过期] 如果我打电话给sample . stackoverflowfile(使用有效文件),那么我会得到usage: sample [-h] directory_path FILES [FILES ...] sample: error: argument FILES: invalid choice: 'stackoverflowfile' (choose from ['sample', '.idea', 'stackoverflowfile'])
  • 你生成了一个错误的choices。将其与简单的choices=['one','two'] 列表进行比较。

标签: python-3.x autocomplete argparse


【解决方案1】:

首先值得一步 argcomplete documentation 在此基础上我创建了一个解决方案

#!/usr/bin/python3
# PYTHON_ARGCOMPLETE_OK

import argparse
import os

import argcomplete


def files_names(prefix, parsed_args, **kwargs):
    absolute_pat = os.path.abspath(parsed_args.directory_path[0])
    files = [file for file in os.listdir(absolute_pat) if os.path.isfile(os.path.join(absolute_pat, file))]

    return files


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument("directory_path",
                        help="a path to some directory",
                        nargs=1)

    parser.add_argument("files",
                        metavar="FILES",
                        nargs='+').completer = files_names

    argcomplete.autocomplete(parser)
    args = parser.parse_args()

    print("directory_path {}".format(args.directory_path))
    print("files {}".format(args.files))

*usesfull snippet 来自 argcomplete 测试目录

要调试完成,您可以在 shell 中设置 _ARC_DEBUG 变量以启用详细调试输出

【讨论】:

    猜你喜欢
    • 2013-05-20
    • 2013-03-17
    • 2019-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-04
    • 1970-01-01
    相关资源
    最近更新 更多