Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何让Python ArgParse停止覆盖子解析器中的位置参数_Python_Python 3.x_Argparse - Fatal编程技术网

如何让Python ArgParse停止覆盖子解析器中的位置参数

如何让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='?'。这样的位置总是“可见”,因为空

我正试图让脚本正常工作,但argparse不断覆盖父解析器中的位置参数。我如何才能让argparse尊重父级的这些值?它会保留可选参数中的值

这是我需要的一个非常简化的版本。如果运行此命令,您将看到args被覆盖

testargs.py 并用
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"