所以我正在编写这个非常小的程序来执行http获取和发布请求。请求如下:
requestApp.py help
requestApp.py help get
requestApp.py help post
requestApp.py get [-v] [-h key:value] URL
requestApp.py post [-v] [-h key:value] [-d inline-data] [-f file] URL
如您所见,-v,-h,-d,-f,URL参数是可选的。 get和post参数是非可选的。我将向您展示与这种情况相关的程序片段:
parser = argparse.ArgumentParser(description='httpc is a curl-like application but supports HTTP protocol only.')
parser.add_argument('command', type=str, help=help_output())
parser.add_argument('url', action='store_true', help='The URL that will be provided to perform the requested command.')
parser.add_argument('-v', '--verbose', action='store_true')
command
参数将是help,get或post,而url
参数是不言自明的。我的问题与上面的第二和第三条命令有关,即:
requestApp.py help get
requestApp.py help post
如何确保在键入help get
时,get
不会在URL中注册(与help post
相同)。另外,当我包含URL时,我希望将其存储在URL参数内。我是否必须手动评估通过if语句传递的参数?还是有更好的方法呢?
答案 0 :(得分:1)
使用argparse
进行操作非常复杂,这里是如何使用docopt
进行操作,docopt
解析使用模式并返回字典:
"""
Usage:
requestApp help [get|post]
requestApp get [-v] [-k=key:value] <URL>
requestApp post [-v] [-k=key:value] [-d=data] [-f file] <URL>
Options:
-v --verbose This is verbose mode
-d=data This option does this
-k=key:value This one does that
-f file This one is magic
"""
from docopt import docopt
ARGS = docopt(__doc__)
例如,使用requestApp.py post -k hello:world -f myfile.txt google.com
docopt将返回:
{
"--verbose": false,
"-d": None,
"-f": "myfile.txt",
"-k": "hello:world",
"<URL>": "google.com",
"get": false,
"help": false,
"post": true
}
那么您可以做:
if ARGS['help']:
if ARGS['get']: pass # requestApp help get
else if ARGS['post']: pass # requestApp help post
else: pass # requestApp help
exit()
if ARGS['get']: pass # requestApp get
else if ARGS['post']: pass # requestApp post
if ARGS['--verbose']: print("this is just the beginning")
-h
是默认情况下(用于帮助)的保留选项,使docopt返回使用模式并退出。
如果您尝试使用docopt
requestApp help unicorn
会将使用模式返回到stdout并退出。
答案 1 :(得分:1)
至少在不使用子解析器路线的情况下,可能最接近argparse
解决方案的地方是:
import argparse
import sys
print(sys.argv)
parser = argparse.ArgumentParser()
parser.add_argument('-k', '--keyvalue')
parser.add_argument('-v', '--verbose', action='store_true')
parser.add_argument('-d', '--data')
parser.add_argument('-f', '--file')
parser.add_argument('pos1', choices = ['help', 'get', 'post'])
parser.add_argument('pos2')
args = parser.parse_args()
print(args)
得到的帮助是:
1744:~/mypy$ python stack54383659.py get aurl -h
['stack54383659.py', 'get', 'aurl', '-h']
usage: stack54383659.py [-h] [-k KEYVALUE] [-v] [-d DATA] [-f FILE]
{help,get,post} pos2
positional arguments:
{help,get,post}
pos2
optional arguments:
-h, --help show this help message and exit
-k KEYVALUE, --keyvalue KEYVALUE
-v, --verbose
-d DATA, --data DATA
-f FILE, --file FILE
合身并不完美。例如,您可以仅提供help
,但是您可以仅提供-h
。第二个位置值可以是任何字符串,“ get”,有效的URL或其他任何内容。您自己的代码必须对此进行验证。 key:value
位需要您自己进行解析。
以argparse
解析optionals
的方式可以以任何顺序发生。这两个位置必须以给定的顺序(相对于彼此)出现。
在较新的Python中,我可以将最后一个位置更改为“可选”,并使用新的intermixed
解析器。那将允许我只给出“帮助”(或只是“得到”):
parser.add_argument('pos2', nargs='?')
args = parser.parse_intermixed_args()
如果两个位置值由标志分开,则需要 intermixed
。由于某些复杂的原因,常规解析可能会消耗“?”参数过早地给您留下了额外的无法识别的字符串。
另一种方法是定义所有标记的参数,并使用parse_known_args
。非标志值将在extras
列表中,您可以根据需要对其进行解析。像optparse
这样的较早的解析器实际上就是这样做的。 argparse
也增加了处理位置参数的能力,但严格按位置而不是按值。