【问题标题】:argparse: optional argument between positional argumentsargparse:位置参数之间的可选参数
【发布时间】:2020-10-02 01:14:03
【问题描述】:

我想模拟大多数命令行实用程序的行为,其中可选参数可以放在命令行中的任何位置,包括 between 位置参数,例如在这个mkdir 示例中:

mkdir before --mode 077 after

在这种情况下,我们知道 --mode 正好有 1 个参数,因此 beforeafter 都被视为位置参数。可选部分,--mode 077,真的可以放在命令行中任何地方

但是,对于argparse,以下代码不适用于此示例:

# mkdir.py
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--mode', nargs=1)
parser.add_argument('dirs', nargs='*')
args = parser.parse_args()

运行./mkdir.py before --mode 077 after 会导致:

mkdir.py: error: unrecognized arguments: after

如何让argparse 接受位置参数之间的可选参数(具有固定的、已知数量的项目)?

【问题讨论】:

标签: python argparse


【解决方案1】:

Python 3.7开始,貌似argparse现在支持这种Unix风格的解析:

混合解析

ArgumentParser.parse_intermixed_args(args=None, namespace=None)

许多 Unix 命令允许用户将可选参数与位置参数混合。 parse_intermixed_args()parse_known_intermixed_args() 方法支持这种解析方式。

有一个警告,但对于“简单”选项,它不会影响它们:

这些解析器不支持所有 argparse 功能,如果使用不受支持的功能,则会引发异常。特别是,不支持子解析器、argparse.REMAINDER 以及同时包含可选项和位置的互斥组。

(我花了 1 小时试图理解为什么 Python argparse 文档中的示例似乎没有包含它之后,我发布了这个常见问题解答风格的问题,只是偶然发现了一个有点不相关的问题,其中包含在评论中提到这个“混合”功能,我无法再次找到正确引用它。)

【讨论】:

  • 这个解析器有点杂乱无章,在常规 parse_known_args 之上运行。它“停用”位置,解析选项,并单独处理“额外”。有关详细信息,请参阅方法的代码。如前所述,它是在 3.7 版中作为新功能添加的。它不会修改常规解析。
【解决方案2】:

我不熟悉 argparse,所以我会编写自己的代码来处理参数。

import sys

#the first argument is the name of the program, so we skip that
args = sys.argv[1:]
#just for debugging purposes:
argsLen = len(args)
print(args, argsLen)

#Create a list that will contain all of the indeces that you will have parsed through
completedIndeces = []
i = 0

#add the index to the completed indeces list.
def goToNextIndex(j):
    global i
    completedIndeces.append(j)
    i += 1

def main():
    global i
    ###core logic example
    #Go through each item in args and decide what to do based on the arugments passed in
    for argu in args:
        if i in completedIndeces:
            print("breaking out")
            #increment i and break out of the current loop
            i += 1
            # If the indeces list has the index value then nothing else is done.
            pass 
        elif argu == "joe":
            print("did work with joe")
            goToNextIndex(i)
        elif argu == "sam":
            print("did work with sam")
            goToNextIndex(i)
        elif argu == "school":
            print("going to school")
            goToNextIndex(i)

            # If the argument has other arguments after it that are associated with it 
            # then add those indeces also to the completed indeces list. 
    
            #take in the argument following school
            nextArg = i
            #Do some work with the next argument
            schoolName = args[nextArg]
            print(f"You're going to the school called {schoolName}")
            #make sure to skip the next argument as it has already been handled
            completedIndeces.append(nextArg)
        else:
            print(f"Error the following argument is invalid: {argu}")
            goToNextIndex(i)


    print(f"Value of i: {i}")
    print(f"completed indeces List: {completedIndeces}")

main()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-27
    • 2023-04-02
    • 2019-04-13
    • 2014-12-29
    • 1970-01-01
    • 2020-11-10
    相关资源
    最近更新 更多