有没有办法让用户选择使用script.py --file c:/stuff/file.txt
,而不是用户必须使用--file
?所以相反,它看起来像script.py c:/stuff/file.txt
但是解析器仍然知道用户正在引用--file参数(因为它是隐含的)。
答案 0 :(得分: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.
有一点需要注意的是,位置file
会覆盖可选--file
并将args.file
设置为默认值''。为了解决这个问题,我使用自定义action
作为位置file
。它禁止覆盖已经设置的属性。
要注意的另一件事是,而不是提出Exception
,你可以指定默认值。
答案 1 :(得分: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.file
(无None
),然后检查--file
,以及{是否args.args
,而不仅仅是args.file
{1}} 不 None
,您仍然可以查看args.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
字符串开头。
答案 2 :(得分:2)
要接受--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
答案 3 :(得分:0)
您可以使用required=True
中的argparse
标记:
import argparse
parser = argparse.ArgumentParser(description="Describe stuff.")
parser.add_argument('--foo', required=True, help='bar')
然而,由于用户希望选项是可选的,因此this documentation says被认为是不好的形式,因为用户需要选项。
您可以改为定义所需的参数,然后将可选的--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")
答案 4 :(得分:0)
在你的设计中,存在一个主要的模糊性(这已经是argparse
未实现的原因的合理解释):
foo/--foo
和bar
),那么应该在像{{1}这样的cmdline中指定位置参数。 }?如果存在多个“双模式”args,这就变得更加混乱。在我两年前编写的使用“双模”参数的脚本中,我完全禁止这样的输入,要求首先使用“位置模式”参数(如果有的话),然后是“命名模式”参数。
脚本在Perl中,我使用自定义逻辑在使用Perl的--foo=foo bar
以“传递”模式解析其他选项(它通过任何无法识别的参数)后实现这一点。
所以我建议您使用ArgumentParser.parse_known_args()
进行相同操作。