使用 argparse 中的子命令创建解析器,自定义位置参数 [英] Create parser with subcommands in argparse, customize positional argument(s)

查看:22
本文介绍了使用 argparse 中的子命令创建解析器,自定义位置参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对这个模块很陌生,所以请耐心等待.我有以下代码:

I'm very new to this module so please bear with me. I have the following code:

import argparse

parent_parser = argparse.ArgumentParser(description="Read text files.")
parent_parser.add_argument('filename', help='TXT file', type=file, nargs='+')
parent_parser.add_argument('--verbose', '-v', action='store_true', 
        help="Verbosity on")

child_parser = parent_parser.add_subparsers(title="subcommand",
        help="Subcommand help")
new_file_command = child_parser.add_parser('new', help="New text file")
edit_file_command = child_parser.add_parser('edit', help="Edit existing text file")

args = parent_parser.parse_args()

我想要实现的可能不是解析器和 unix 命令行实用程序如何工作的标准方式.如果这是真的,请纠正我,因为我想要标准化的应用程序.

What I'm trying to achieve might not be the standard way of how parsers and unix command line utilities work. If that is true, please correct me as I'd like to have standardized app.

这就是我想要实现的目标:

This is what I'm trying to achieve:

  • 如果您使用这样的位置参数运行裸脚本:python reader.py some.txt 我希望能够解析它并将其传递给读取文本文件,当然我也想接受可选的 arg verbose
  • 如果您运行子命令new"(new_file_command),我不希望需要位置参数filename,而是希望传递一个字符串并创建像这样的新文本文件:python reader.py new another.txt
  • 如果你运行子命令 'edit' (edit_file_command) 我想在路径中传递现有文件并检查它(就像你在 中使用 type=intadd_argument) 然后可能将其传递给打开编辑器的函数,如下所示:python reader.py edit some.txt
  • if you run bare script with positional argument(s) like this: python reader.py some.txt I'd like to be able to just parse it and pass it to function that reads the text file, of course I want to accept optional arg verbose as well
  • if you run subcommand 'new' (new_file_command), I do not want to have positional argument filename to be required, instead I want to pass a string and create new text file like this: python reader.py new another.txt
  • if you run subcommand 'edit' (edit_file_command) I want to pass existing file in path and check for it (like you use type=int in add_argument) and then maybe pass it to function that opens editor, something like this: python reader.py edit some.txt

同样,我不确定这是否是命令行应用程序/脚本的行为方式.我阅读了文档并查看了示例,但我仍然不清楚子解析器是如何工作的.我尝试查看 Click 模块,但在我看来这更复杂.

Again, I'm not sure if this is how command line apps/scripts are supposed to behave. I read the docs and looked at examples but it's still isn't clear to me how sub parsers work. I tried looking at Click module but that seems to me even more complicated.

任何帮助表示赞赏.谢谢!

Any help appreciated. Thanks!

推荐答案

所以三个示例调用是:

python reader.py some.txt 
python reader.py new another.txt
python reader.py edit some.txt

处理这些问题的最简单方法是使用一个可选"位置和一个必需的.

The easiest way to handle these is with one 'optional' positional, and one required one.

parser = ArgumentParser...
parser.add_argument('-v','--verbose', ...)
parser.add_argument('cmd', nargs='?', default='open', choices=['open','edit','new'])
parser.add_argument('filename')

对于您的 3 个样本,它应该产生如下结果:

For your 3 samples, it should produce something like:

namespace(cmd='open', filename='some.txt')
namespace(cmd='new', filename='another.txt')
namespace(cmd='edit', filename='some.txt')

cmd 是一个可选的位置参数.如果缺少,则将一个字符串分配给filenamecmd 获取其default.这样做比尝试将 subparsers 设为可选更容易.

cmd is an optional positional argument. If it is missing, the one string will be allocated to filename, and cmd gets its default. It's easier to do this than trying make a subparsers optional.

至于您当前的解析器:

parent_parser = argparse.ArgumentParser(description="Read text files.")
parent_parser.add_argument('filename', help='TXT file', type=file, nargs='+')

我不推荐使用 type=file.最好使用 FileType 或默认字符串(它允许您稍后在 with context 中打开文件).

I would not recommend using type=file. Better to use FileType or the default string (which lets you open the file in a with context later).

至于 nargs='+',您真的要为 filename 分配 1 或更多 个字符串吗?或者您是否考虑过?",即 0 或 1,即使其成为可选?

As to the nargs='+', do you really want to allocate 1 or more strings to filename? Or were you thinking of '?', which would be 0 or 1, i.e. making it optional?

parent_parser.add_argument('--verbose', '-v', action='store_true', 
        help="Verbosity on")

child_parser = parent_parser.add_subparsers(title="subcommand",
        help="Subcommand help")
new_file_command = child_parser.add_parser('new', help="New text file")
edit_file_command = child_parser.add_parser('edit', help="Edit existing text file")

混合这个 filename 位置,它接受可变数量的值,和一个子解析器参数(一个需要 newedit 的位置)可能有问题.

Mixing this filename positional which accepts a variable number of values, with a subparsers argument (a positional that expects either new or edit) could be a problem.

我希望 'python reader.py some.txt' 反对缺少 subparser 命令.'python reader.py new another.txt' 将尝试将 new 分配给 filenameanother.txt子解析器,并引发错误.

I expect 'python reader.py some.txt' to object that the subparser command is missing. 'python reader.py new another.txt' will try to allocate new to filename, and another.txt to subparser, and raise an error.

最好在所有 3 种情况下都使用 subparsers 命令:

It would be better to expect a subparsers command in all 3 cases:

parent_parser = argparse.ArgumentParser(description="Read text files.")
parent_parser.add_argument('--verbose', '-v', action='store_true', 
        help="Verbosity on")
child_parser = parent_parser.add_subparsers(title="subcommand",
        help="Subcommand help", dest='cmd')
open_file_command = child_parser.add_parser('open', help="Open text file")
open_file_command.add_argument('filename', help='TXT file')
new_file_command = child_parser.add_parser('new', help="New text file")
new_file_command.add_argument('filename', help='TXT file')
edit_file_command = child_parser.add_parser('edit', help="Edit existing text file")
edit_file_command.add_argument('filename', help='TXT file')

每个命令,'open'、'new'、'edit',都需要一个'文件名'.

Each of commands, 'open','new','edit', expects a 'filename'.

试图避免使用 open 命令会带来更多的困难.

Trying to avoid the use of an open command is going to create more difficulties than it's worth.

(最新的 argparse 中有一个错误/功能使子解析器成为可选的,但您不应该在不真正了解问题的情况下利用它.)

(There is a bug/feature in the latest argparse that makes subparsers optional, but you shouldn't take advantage of that without really knowing the issues.)

与:

parser = argparse.ArgumentParser()
parser.add_argument('-v', '--verbose') 
parser.add_argument('cmd', nargs='?', default='open', 
    choices=['open', 'edit', 'new']) 
parser.add_argument('filename', nargs='+') 

我希望 reader.py 新的自定义字符串

namespace(cmd='new', filename=[customstring])

可以用作:

if args.cmd=='new':
with open(args.filename[0] + '.txt', 'w') as f:
     # do something with the newly created file

openedit 将使用不同的 open 模式.

open and edit would use different open modes.

请注意,在 Py3 中,不需要 subparsers.也就是说,如果未提供其中一个子命令,则不会引发错误.这是对早期版本的无意更改.

Beware that in Py3, subparsers are not required. That is, if one of the subcommands is not provided, it won't raise an error. That's an inadvertent change from early versions.

带有所需子解析器的 Argparse

这篇关于使用 argparse 中的子命令创建解析器,自定义位置参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆