3

script.py --file c:/stuff/file.txt没有办法让用户有选择地使用--file?因此,它看起来像script.py c:/stuff/file.txt,但解析器仍然知道用户指的是 --file 参数(因为它是隐含的)。

4

5 回答 5

6

尝试这个

import argparse

class DoNotReplaceAction(argparse.Action):
    def __call__(self, parser, namespace, values, option_string=None):
        if not getattr(namespace, self.dest):
            setattr(namespace, self.dest, values)

parser = argparse.ArgumentParser(description="This is an example.")
parser.add_argument('file', nargs='?', default='', help='specifies a file.', action=DoNotReplaceAction)
parser.add_argument('--file', help='specifies a file.')

args = parser.parse_args()
# check for file argument
if not args.file:
    raise Exception('Missing "file" argument')

看帮助信息。所有参数都是可选的

usage: test.py [-h] [--file FILE] [file]

This is an example.

positional arguments:
  file         specifies a file.

optional arguments:
  -h, --help   show this help message and exit
  --file FILE  specifies a file.

需要注意的一件事是 positionalfile将覆盖 optional--file并设置args.file为默认 ''。为了克服这个问题,我将 customaction用于 positional file。它禁止覆盖已经设置的属性。

Exception要注意的另一件事是,您可以指定默认值,而不是提高。

于 2013-07-17T18:44:00.227 回答
3

要接受一个--file FILE或一个FILE,你可以使用mutually_exclusive_group()

import argparse

parser = argparse.ArgumentParser(prog='script',
                                 description="This is an example.",
                                 usage='%(prog)s [-h] (--file FILE | FILE)')
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('positional_file', nargs='?', help='specifies a file.')
group.add_argument('--file', help='specifies a file.')

args = parser.parse_args()
print(args)
filename = args.positional_file if args.file is None else args.file

例子

['abc'] -> Namespace(file=None, positional_file='abc')

['--file', 'abc'] -> Namespace(file='abc', positional_file=None)

['--file', 'abc', 'def'] -> usage: script [-h] (--file FILE | FILE)
script: error: argument positional_file: not allowed with argument --file

[] -> usage: script [-h] (--file FILE | FILE)
script: error: one of the arguments positional_file --file is required
于 2013-07-17T19:54:24.557 回答
2

如果我可以将您的问题改写为答案,那么您需要一个脚本,该脚本在运行时为:

  • script blah视为blah要打开的文件名
  • script --file blah视为blah要打开的文件名
  • script --file blah eggs视为blah要打开的文件名,并且eggs...如何?
  • script blah eggs对待blah……不同?如何?

无论如何,我仍然会从 argparse 开始:

#! /usr/bin/env python

import argparse

parser = argparse.ArgumentParser(description='script to morgle blahs')
parser.add_argument('--file', help='specify file name to be opened')
parser.add_argument('args', metavar='FILE', nargs='*')
args = parser.parse_args()

print args

此时运行./script.py -h产生:

usage: script.py [-h] [--file FILE] [FILE [FILE ...]]

script to morgle blahs

positional arguments:
  FILE

optional arguments:
  -h, --help   show this help message and exit
  --file FILE  specify file name to be opened

附加运行:

$ ./script.py
Namespace(args=[], file=None)
$ ./script.py blah
Namespace(args=['blah'], file=None)
$ ./script.py --file blah eggs
Namespace(args=['eggs'], file='blah')
$ ./script.py blah eggs
Namespace(args=['blah', 'eggs'], file=None)

因此,print args现在您可以测试是否args.fileNone(否--file)然后检查,而不是args.args简单地检查,如果args.file不是,您仍然可以检查。 Noneargs.args

如果在某个时候,您在自己的代码中决定某些参数组合是错误/无效的,您可以调用parser.error,例如:

if args.file is not None and len(args.args) > 0:
    parser.error('use [--file] <filename>, not --file <filename1> <filename2>')
if args.file is None and len(args.args) != 1:
    parser.error('use [--file] <filename>')

将只要求一个参数,无论前面是否有--file字符串。

于 2013-07-17T18:44:52.633 回答
0

您可以required=True在以下位置使用标志argparse

import argparse

parser = argparse.ArgumentParser(description="Describe stuff.")
parser.add_argument('--foo', required=True, help='bar')

但是,正如本文档所述,将选项设为必需被认为是错误的形式,因为用户希望选项是可选的。

您可以改为定义所需参数,然后将可选--foo标志存储到此所需参数。这可能会导致解析器抛出异常,因为它可能认为您只是忽略了所需的参数。

import argparse

parser = argparse.ArgumentParser(description="Will this work?")
parser.add_argument('bar', help="required argument")
parser.add_argument('--foo', required=False, help="kind of required argument", dest='bar')

我认为最好的答案是没有一个需要的标志。只需将变量设为必需并为其定义默认值,以防您需要在程序中使用某些东西,但默认值以某种方式适用:

import argparse

parser = argparse.ArgumentParser(description="Other option.")
parser.add_argument('bar', default='value', help="required argument")
于 2013-07-17T18:45:49.470 回答
0

在您的设计中,存在一个主要的歧义(这已经是一个合理的解释,为什么它不是由 实现的argparse):

  • 如果在这样的“双模式”之后还有更多的位置参数(例如,foo/--foobar),那么在命令行中应该将位置参数分配给哪个位置参数,例如--foo=foo bar?如果有多个“双模式”参数,这会变得更加混乱。

在我两年前编写的使用“双模式”参数的脚本中,我完全禁止此类输入,要求“位置模式”参数(如果有)首先出现,然后是“命名模式”参数。

该脚本在 Perl 中,在使用 PerlGetopt::Long在“传递”模式下解析其他选项后,我使用自定义逻辑来实现这一点(它传递任何无法识别的参数)。

所以我建议你也这样做,使用ArgumentParser.parse_known_args().

于 2013-08-29T14:37:38.963 回答