如何让Python ArgParse停止覆盖子解析器中的位置参数
我正试图让脚本正常工作,但argparse不断覆盖父解析器中的位置参数。我如何才能让argparse尊重父级的这些值?它会保留可选参数中的值 这是我需要的一个非常简化的版本。如果运行此命令,您将看到args被覆盖 testargs.py 并用如何让Python ArgParse停止覆盖子解析器中的位置参数,python,python-3.x,argparse,Python,Python 3.x,Argparse,我正试图让脚本正常工作,但argparse不断覆盖父解析器中的位置参数。我如何才能让argparse尊重父级的这些值?它会保留可选参数中的值 这是我需要的一个非常简化的版本。如果运行此命令,您将看到args被覆盖 testargs.py 并用testargs.pysomething/tmp/test.txt-d-c 您将看到它保留了-d,但删除了两个位置参数,并将它们恢复为默认值 编辑:有关一些注意事项,请参阅已接受答案中的其他注释。这两个位置是nargs='?'。这样的位置总是“可见”,因为空
testargs.pysomething/tmp/test.txt-d-c
您将看到它保留了-d
,但删除了两个位置参数,并将它们恢复为默认值
编辑:有关一些注意事项,请参阅已接受答案中的其他注释。这两个位置是
nargs='?'
。这样的位置总是“可见”,因为空列表与nargs
匹配
首次通过“text.txt”与First
匹配,并放在名称空间中。第二次到第二次,没有任何字符串可匹配,因此使用默认值-就像第一次没有给出该字符串一样
如果我先将更改为默认的nargs
,我会得到
error: the following arguments are required: first
来自第二个解析器。即使名称空间中有一个值,它仍然尝试从argv
获取一个值。(这类似于违约,但并不完全如此)
带有nargs='?'
(或*
)的位置的默认设置很棘手。它们是可选的,但与optionals
的方式不同。位置动作仍被调用,但值列表为空
我认为家长
功能对您没有任何帮助preparser
已经处理了这组参数;无需在解析器
中再次处理它们,尤其是因为所有相关的参数字符串都已删除
另一个选项是将父级保留在中,但在第二个解析器中使用默认的sys.argv[1://code>。(但要注意打开文件等副作用)
第三种选择是独立解析参数,并将它们与字典update
合并
adict = vars(preparse_args)
adict.update(vars(parser_args))
# taking some care in who overrides who
有关更多详细信息,请查看argparse.py
文件中的ArgumentParser.\u获取\u值
,特别是非arg\u字符串
案例
关于文件类型的说明
。这种类型很适合小脚本,您可以立即使用这些文件并退出。在大型程序中,如果您可能希望在使用后关闭文件(关闭stdout
?),或者在上下文中使用文件,那么这就不太好了
编辑-家长的注意事项
add_参数
创建一个Action
对象,并将其添加到解析器的操作列表中parse_args
基本上将输入字符串与这些操作匹配
父对象
仅将这些操作对象(通过引用)从父对象复制到子对象。对于子解析器来说,这就像是直接使用add_参数
创建操作一样
当您导入解析器并且无法直接访问其定义时,父类
最有用。如果同时定义父项和子项,则父项
只需为您保存一些键入/剪切粘贴
这个问题和其他一些问题(主要是由引用副本触发的)表明,开发人员并不打算让您同时使用父级和子级来进行解析。这是可以做到的,但是他们没有考虑到一些毛病。
===================
我可以想象定义一个自定义的Action
类,该类在这种情况下会“行为”。例如,在添加自己的(可能是默认)值之前,它可能会检查名称空间中的一些非默认值
例如,如果我将first
的操作更改为“append”:
preparser.add_argument('first', action='append', nargs='?')
结果是:
1840:~/mypy$ python3 stack37147683.py /tmp/test.txt -d -c
Namespace(do_something=True, first=['/tmp/test.txt'], outfile=<_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>)
Namespace(clear_screen=True, do_something=True, first=['/tmp/test.txt', None], outfile=<_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>)
1840:~/mypy$python3 stack37147683.py/tmp/test.txt-d-c
命名空间(do_something=True,first=['/tmp/test.txt'],outfile=)
命名空间(clear\u screen=True,do\u something=True,first=['/tmp/test.txt',None],outfile=)
在第一个解析器中,first=['/tmp/test.txt']
;从第二个开始,first=['/tmp/test.txt',None]
由于append
,第一个语法分析器中的项被保留,第二个语法分析器添加了一个新的默认值。两个位置是nargs='?'
。这样的位置总是“可见”,因为空列表与nargs
匹配
首次通过“text.txt”与First
匹配,并放在名称空间中。第二次到第二次,没有任何字符串可匹配,因此使用默认值-就像第一次没有给出该字符串一样
如果我先将更改为默认的nargs
,我会得到
error: the following arguments are required: first
来自第二个解析器。即使名称空间中有一个值,它仍然尝试从argv
获取一个值。(这类似于违约,但并不完全如此)
带有nargs='?'
(或*
)的位置的默认设置很棘手。它们是可选的,但与optionals
的方式不同。位置动作仍被调用,但值列表为空
我认为家长
功能对您没有任何帮助preparser
已经处理了这组参数;无需在解析器
中再次处理它们,尤其是因为所有相关的参数字符串都已删除
另一个选项是将父级保留在中,但在第二个解析器中使用默认的sys.argv[1://code>。(但要注意打开文件等副作用)
第三种选择是独立解析参数,并将它们与字典update
合并
adict = vars(preparse_args)
adict.update(vars(parser_args))
# taking some care in who overrides who
有关更多详细信息,请查看argparse.py
文件中的ArgumentParser.\u获取\u值
,特别是非arg\u字符串
import argparse
parser1 = argparse.ArgumentParser(add_help=False)
parser1.add_argument("first")
parser2 = argparse.ArgumentParser(parents=[parser1])
parser2.add_argument("second")
args2 = parser2.parse_args(["arg1","arg2"])
assert args2.first == "arg1" and args2.second == "arg2"
parser1 = argparse.ArgumentParser(add_help=False)
parser1.add_argument("first")
args1, remaining_args = parser1.parse_known_args(["arg1","arg2"])
parser2 = argparse.ArgumentParser(parents=[parser1])
parser2.add_argument("second")
>>> args1
Namespace(first='arg1')
>>> remaining_args
['arg2']
>>> parser2.parse_args(remaining_args)
usage: test.py [-h] first second
test.py: error: the following arguments are required: second
parser1 = argparse.ArgumentParser(add_help=False)
parser1.add_argument("first")
args1, remaining_args = parser1.parse_known_args(["arg1","arg2"])
parser2 = argparse.ArgumentParser() #parents=[parser1]) #NO PARENT!
parser2.add_argument("second")
args2 = parser2.parse_args(remaining_args,args1)
assert args2.first == "arg1" and args2.second == "arg2"