创建于argparse子分析器,自定义位置参数(S)(Create parser with subc

2019-10-22 22:06发布

我非常新的这个模块,所以请多多包涵。 我有以下代码:

reader.py

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命令行实用程序是如何工作的标准方式。 如果这是真的,请大家指正,因为我想有标准化的应用程序。

这就是我想要实现:

  • 如果您运行位置参数(一个或多个)这样的裸脚本: python reader.py some.txt我想能够只是解析它,并把它传递给函数读取文本文件,我当然要接受可选精氨酸verbose以及
  • 如果您运行的子命令“新”( new_file_command ),我不希望有位置参数filename来要求,而不是我想传递一个字符串,创建这样新的文本文件: python reader.py new another.txt
  • 如果您运行的子命令“编辑”( edit_file_command )我想通过现有的文件路径,并检查它(就像你使用type=intadd_argument ),然后也许它传递的功能,打开编辑器,像这样: python reader.py edit some.txt

同样,我不知道这是怎么命令行应用程序/脚本都应该表现。 我阅读文档,看着例子,但它仍然不是很清楚,我的子分析器是如何工作的。 我试图寻找在点击模块,而是更加复杂在我看来。

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

Answer 1:

所以,三个采样电话是:

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

处理这些最简单的办法是用一个“可选”位置,以及一个要求之一。

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

对于你的3个样本,它应该产生这样的:

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

cmd是一个可选的位置参数。 如果丢失,一个字符串将被分配给filename ,并cmd获取其default 。 它更容易做到这一点不是试图做一个subparsers可选。


至于当前的解析器:

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

我不建议使用type=file 。 更好地使用FileType或默认的字符串(它可以让你在打开文件with context更高版本)。

至于nargs='+' ,你真的想分配1 or more字符串filename ? 或者是怎么想的“?”,这将是0 or 1 ,即使其可选?

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 )可能是一个问题。

我希望'python reader.py some.txt'到对象,它是缺失的子分析器命令。 'python reader.py new another.txt'会尝试分配newfilename ,并another.txt到子分析器,并引发错误。

这将是更好地在所有3个案件期望subparsers命令:

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命令是要创造更多的困难比它的价值。

(有一个在使subparsers可选最新argparse一个bug /功能,但你不应该利用这一点没有真正知道的问题。)


附:

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模式。


要注意的是在PY3, subparsers不是必需的。 也就是说,如果不提供的子命令之一,它不会引发错误。 这是从早期版本中的意外更改。

有需要的子分析器Argparse



文章来源: Create parser with subcommands in argparse, customize positional argument(s)