2015-05-02 92 views
1

我对这个模块非常陌生,所以请耐心等待。我有以下代码:使用argparse中的子命令创建解析器,自定义位置参数

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

同样,我不确定这是命令行应用程序/脚本应该如何表现。我阅读了文档并查看了示例,但对于我来说,还不清楚子解析器是如何工作的。我试着看看Click模块,但在我看来,这更复杂。

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

回答

2

所以三个示例电话是:

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

我希望​​反对subparser命令丢失。 'python reader.py new another.txt'会尝试将new分配给filenameanother.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模式。

+0

嗨,感谢您的帮助。我还有最后一个问题。我仍然想知道如何定制位置参数。假设我有以下代码: parser = argparse.ArgumentParser() parser.add_argument(' - v','--verbose') parser.add_argument('cmd',nargs ='?',default ='open ',options = ['open','edit','new']) parser.add_argument('filename',nargs ='+') 如果我想自定义命令'new'的位置参数?我不需要/希望传递明确的文件名,而只需要一个像'some'这样的字符串,然后创建文件'some.txt'。我该怎么做呢?谢谢 – user3056783

+0

你可以创建一个自定义的'type'或'Action'。但通常在解析后进行这种更改会更简单。特别是如果你没有对“某些”进行错误检查。 – hpaulj

+0

嗨我还在阅读文档,并试图找出这一点,但我无法在网上找到更多的例子。你能告诉我一个片段,你将如何实现这个解析后?因为如果我执行'reader.py new customstring',它会对现有文件名进行错误检查,所以它不会让我做任何事情。 – user3056783