5

我有一个接受文件作为输入的程序,对文件的内容进行一些处理并将其推送到服务器。我想添加一个可选的命令行开关来指定程序的“空运行”,它会执行所有文件处理,但会跳过写入服务器的操作。我正在使用 argparse 引入命令行参数,但我看不到在参数之间执行“OR”函数的方法。这就是我或多或少在寻找的东西......

允许的选项:

1) prog.py 输入文件服务器名

2) prog.py 输入文件 -d

3) prog.py 输入文件 -d 服务器名

不允许:

1) prog.py 输入文件

我想确保服务器名称“或”试运行标志在命令行上。而且,如果两者都在那里……那也没关系。(因此是 OR 而不是 XOR)。如果我用 required=true 互斥,我可以得到 XOR;但是,我似乎无法弄清楚如何将其作为“或”来执行,其中两者都可以存在。更复杂的是,服务器名称是一个位置参数,而试运行标志是一个可选参数,可以在命令行的任何位置。有谁知道如何解决这个问题?

4

3 回答 3

7

这是我要做的:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-d', '--dry-run', action='store_true')
parser.add_argument('input_file', type=argparse.FileType('r'))
parser.add_argument('servername', nargs='?')

args = parser.parse_args()
if args.servername is None and not args.dry_run:
    parser.error("Option 'servername' is required when not in dry-run mode.")

print args

例子:

$ ./prog.py inputfile servername
Namespace(dry_run=False, input_file=<open file 'inputfile', mode 'r' at 0x283440>, servername='servername')
$ ./prog.py inputfile -d
Namespace(dry_run=True, input_file=<open file 'inputfile', mode 'r' at 0x2cf440>, servername=None)
$ ./prog.py -d inputfile servername
Namespace(dry_run=True, input_file=<open file 'inputfile', mode 'r' at 0x1f4440>, servername='servername')
$ ./prog.py inputfile
usage: prog.py [-h] [-d] input_file [servername]
prog.py: error: Option 'servername' is required when not in dry-run mode.

您也可以使用自定义操作来执行此操作,它具有相同的效果:

class ServernameAction(argparse.Action):
    def __call__(self, parser, namespace, values, option_string=None):
        if values is None and not namespace.dry_run:
            parser.error("Option 'servername' is required when not in dry-run mode.")
        setattr(namespace, self.dest, values)

...
parser.add_argument('servername', nargs='?', action=ServernameAction)
...
于 2012-09-21T18:48:29.553 回答
3

argparse无法完成所有可能的验证组合,因此值得学习如何在事后添加自己的验证。例如:

parser = argparse.ArgumentParser(epilog='Either foo or bar (or both) must be specified.')
parser.add_argument('--foo', help='do something.')
parser.add_argument('--bar', help='do something else.')
args = vars(parser.parse_args())
if not args['foo'] and not args['bar']:
  parser.error('Either foo or bar (or both) must be specified.')
于 2012-09-21T18:46:11.600 回答
0

由于如果-d使用服务器名称将被忽略,因此给它一个默认值,如果您尝试使用它肯定会导致错误(无论如何您都需要验证它,对吗?):

p.add_argument("server", default=None)

如果-d给出,您可能永远不会同时验证或使用服务器名称,并且一切都很好。否则,您的代码将在尝试验证错误的服务器名称时捕获它。

于 2012-09-21T18:46:50.930 回答