Python argparse:位置参数之间的可选参数

Python argparse:位置参数之间的可选参数,python,argparse,Python,Argparse,我想模拟大多数命令行实用程序的行为,其中可选参数可以放在命令行中的任何位置,包括位置参数之间,例如在下面的mkdir示例中: mkdir before --mode 077 after 在本例中,我们知道,--mode只接受一个参数,因此在之前和在之后都被视为位置参数。可选部分--mode 077,实际上可以放在命令行中的任何位置 但是,对于argparse,以下代码不适用于此示例: # mkdir.py import argparse parser = argparse.ArgumentPa

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

mkdir before --mode 077 after
在本例中,我们知道,
--mode
只接受一个参数,因此
之前和
之后都被视为位置参数。可选部分--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,在之后运行模式077,将导致:

mkdir.py: error: unrecognized arguments: after
如何让
argparse
接受位置参数之间的可选参数(具有固定的已知项数)?

从开始,似乎
argparse
现在支持这种Unix风格的解析:

混合句法分析
ArgumentParser.parse_mixed_args(args=None,namespace=None)

许多Unix命令允许用户将可选参数与位置参数混合使用。
parse_mixed_args()
parse_known_mixed_args()
方法支持这种解析风格

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

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


(我花了一个小时试图理解为什么Python
argparse
文档中的示例似乎没有包含这个问题,然后我发布了这个FAQ风格的问题,只是碰巧发现了一个不太相关的问题,其中包含了对这个“混合”的提及。)函数在注释中,我无法再次找到它来正确引用。)

我不熟悉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()

确切地说,它不是“大多数”实用程序,而是那些使用库的实用程序不将第一个非可选参数视为选项的结束(例如GNU
getopts
)。
argparse
不支持这种样式。相关:这个解析器有点笨拙,在常规的
parse\u args
之上运行。它“停用”位置,解析选项,并单独处理“附加”。有关详细信息,请参阅方法的代码。如前所述,它是与3.7版一起添加的一项新功能。它不修改常规解析。