在Python中以前缀表示法处理命令行参数

ejm*_*ejm 7 python stack prefix command-line-arguments data-structures

我正在尝试解析Python中的命令行,如下所示:

$ ./command -o option1 arg1 -o option2 arg2 arg3
Run Code Online (Sandbox Code Playgroud)

换句话说,该命令采用无限数量的参数,并且每个参数可以可选地在前面加上一个-o选项,该选项与该参数具体相关.我认为这被称为"前缀表示法".

在Bourne shell中,我会做类似以下的事情:

while test -n "$1"
do
    if test "$1" = '-o'
    then
        option="$2"
        shift 2
    fi
    # Work with $1 (the argument) and $option (the option)
    # ...
    shift
done
Run Code Online (Sandbox Code Playgroud)

看看Bash教程等,这似乎是公认的习惯用法,所以我猜测Bash已经过优化,可以通过这种方式使用命令行参数.

试图在Python中实现这种模式,我的第一个猜测是使用pop(),因为这基本上是一个堆栈操作.但我猜这在Python上不会有效,因为参数列表的sys.argv顺序错误,必须像队列一样处理(即从左侧弹出).我已经读过,列表没有优化用作Python中的队列.

所以,我的想法是:转换argvcollections.deque和使用popleft(),反向argv使用reverse()和使用pop(),或者只是使用int列表索引本身.

有没有人知道更好的方法来做到这一点,否则我的哪些想法将是最好的Python实践?

jfs*_*jfs 7

另一个stdlib模块:argparse

p = argparse.ArgumentParser()
p.add_argument('-o', action='append')
for i in range(1, 4): p.add_argument('arg%d' % i)
args = p.parse_args('-o option1 arg1 -o option2 arg2 arg3'.split())
print args
# -> Namespace(arg1='arg1', arg2='arg2', arg3='arg3', o=['option1', 'option2'])
Run Code Online (Sandbox Code Playgroud)


Dav*_*d Z 5

你可以做

argv.pop(0)
Run Code Online (Sandbox Code Playgroud)

拉出第一个元素并返回它.但这可能效率低下.也许.我不确定如何argv在引擎盖下实施.(再说,如果效率重要的,为什么你使用Python是谁?)

但是,更多的Pythonic解决方案是迭代列表而不会弹出元素.像这样:

o_flag = False
for a in argv:
    if a == '-o':
        o_flag = True
        continue
    # do whatever
    o_flag = False
Run Code Online (Sandbox Code Playgroud)

此外,我认为该optparse模块值得一提; 它是处理Python程序中的选项和参数的标准,尽管它可能对此任务有点过分,因为您已经拥有几个功能完善的解决方案.


Iva*_*n X 5

可以通过导入sys,然后将sys.argv [1:]分配给变量(例如“ args”)来获得Bourne / Bash中与“ shift”等效的Python功能。然后,您可以使用args = args [1:]左移一次,或使用更高的数字多次移入。参数索引将从0开始,而不是1。上面的示例如下所示:

import sys
args = sys.argv[1:]
while len(args):
    if args[0] == '-o':
        option = args[1]
        args = args[2:] # shift 2
    # Work with args[0] (the argument) and option (the option)
    # ...
    args = args[1:] # shift
Run Code Online (Sandbox Code Playgroud)