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

查看:52
本文介绍了在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.

这是我要实现的目标:

  • 如果您运行带有位置参数的裸脚本,例如:python reader.py some.txt我希望能够解析它并将其传递给读取文本文件的函数,当然我想接受可选的arg verbose也是
  • 如果您运行子命令'new'(new_file_command),则我不需要位置参数filename,而是希望传递字符串并创建新的文本文件,如下所示:python reader.py new another.txt
  • 如果您运行子命令'edit'(edit_file_command),我想在路径中传递现有文件并进行检查(例如您在add_argument中使用type=int),然后将其传递给打开编辑器的功能,像这样的东西: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!

推荐答案

因此,有三个示例调用:

So three sample calls are:

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是可选的位置参数.如果丢失,则将一个字符串分配给filename,而cmd获得其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 or more字符串吗?还是您在考虑'?',它是0 or 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位置变量与可变数量的值混合,并使用subparsers自变量(期望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分配给filename,将another.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'都需要一个'filename'.

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 new customstring给予

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天全站免登陆