从 Python 中的命名空间获取所需选项
Getting required option from Namespace in Python
我这样创建一个 ArgumentParser:
argpr = ArgumentParser()
argpr.add_argument('--long-c', '-c', required=True, dest='long_c')
如果存在 json 配置文件,我将配置添加到命名空间:
cfg = argparse.Namespace()
if json_dict is not None:
cfg.long_c = json['long-c']
print vars(cfg)
然后我使用命名空间作为参数解析器的参数,如下所示:
use_cfg = argpr.parse_args(namespace=cfg)
我可以看到我在我的命名空间对象中得到了一个值,因此我希望 ArgumentParser.parse_args 在我的命名空间对象中找到 long_c 但我得到:
argument --long-c/-c is required
我是不是做错了什么?这是错误还是预期的行为?欢迎就如何使这项工作提出任何建议 =)
提前致谢
编辑:
- 修正错别字。
- 将命名空间更改为命名空间对象。
- 澄清了我对命名空间对象的使用和我的期望。
Namespace
不是用来传递参数而是用来存储结果的。您需要在 args
参数中传递配置。我认为这就是您所追求的:
cfg = []
if json_dict is not None:
cfg.extend(('-c', json['long-c']))
use_cfg = argpr.parse_args(cfg)
我明白您要做什么,但我认为 argparse
不会按照您希望的方式检查命名空间中的必需参数。通常您不需要提供 namespace
参数,但如果您希望将解析后的参数分配给现有对象,这会很好。
此外,如果您确实想要显式创建一个Namespace
,请务必实例化它:
# use this:
argparse.Namespace()
# not this:
argparse.Namespace
否则,您最终会将属性分配给 Namespace
class 本身。
另请阅读 required
上的注释:
Note: Required options are generally considered bad form because users
expect options to be optional, and thus they should be avoided when
possible.
您创建和使用命名空间的方式没有任何问题(在您进行更正之后),但正如 André Laszlo 提到的,您的期望是错误的:
...I expect that ArgumentParser.parse_args finds long_c in my
Namespace object but I get:
argument --long-c/-c is required
很容易证明 argparse 不是那样工作的:
import argparse as ap
argpr = ap.ArgumentParser()
argpr.add_argument('--long-c', '-c', required=True, dest='long_c')
cfg = ap.Namespace()
print(cfg)
name_space = argpr.parse_args(namespace=cfg)
print(name_space.long_c)
print(name_space) #name_space and cfg are different names for the same object
--output:--
$ python3.4 1.py -c 4
Namespace()
4
Namespace(long_c='4')
(注意,如果你希望存储的值是一个int,那么你可以在add_argument()中加上type=int
)
现在 cfg 命名空间已经具有 long_c
的值:
import argparse as ap
argpr = ap.ArgumentParser()
json_dict = {'long-c': 5}
cfg = ap.Namespace()
if json_dict:
cfg.long_c = json_dict['long-c']
print(cfg)
argpr.add_argument('--long-c', '-c', required=True, dest='long_c')
name_space = argpr.parse_args(namespace=cfg)
print(name_space.long_c)
print(name_space) #name_space and cfg are different names for the same object
--output:--
$ python3.4 1.py -c 4
Namespace(long_c=5)
4
Namespace(long_c='4')
但是...
$ python3.4 1.py
Namespace(long_c=5)
usage: 1.py [-h] --long-c LONG_C
1.py: error: the following arguments are required: --long-c/-c
要得到你想要的行为,你需要使 -c
选项 可选 如果 json_dict 已经有一个值,像这个:
cfg = ap.Namespace()
required = True
if json_dict:
val = json_dict.get('long-c', False)
if val:
cfg.long_c = val
required = False
print(cfg)
argpr.add_argument('--long-c', '-c', required=required, dest='long_c')
我将 ArgumentParser
子类化来做你想让它做的事。
import json
from argparse import ArgumentParser
class ConfigurableArgumentParser(ArgumentParser):
def __init__(self, config_file, *args, **kwargs):
self.config = json.load(config_file)
super(ConfigurableArgumentParser, self).__init__(*args, **kwargs)
def add_argument(self, *args, **kwargs):
store_action = super(ConfigurableArgumentParser, self).add_argument(
*args, **kwargs)
dest = store_action.dest
if dest in self.config:
store_action.default = self.config[dest]
store_action.required = False
return store_action
这个参数解析器接受一个额外的构造函数参数,config_file
它应该是一个指向 JSON 配置文件的文件对象。 add_argument
方法被修改为使用配置文件中的默认值(如果存在),在这种情况下 required
也将设置为 False
.
用法:
if __name__ == '__main__':
from StringIO import StringIO
# config_file = open('my_config.json')
config_file = StringIO('{"long_c": "1"}')
parser = ConfigurableArgumentParser(config_file)
parser.add_argument('--long-c', '-c',
required=True, dest='long_c', type=int)
namespace = parser.parse_args()
print namespace
# Output:
# Namespace(long_c=1)
请注意,类型仍按应有的方式处理,JSON 字符串自动转换为 int
。
我这样创建一个 ArgumentParser:
argpr = ArgumentParser()
argpr.add_argument('--long-c', '-c', required=True, dest='long_c')
如果存在 json 配置文件,我将配置添加到命名空间:
cfg = argparse.Namespace()
if json_dict is not None:
cfg.long_c = json['long-c']
print vars(cfg)
然后我使用命名空间作为参数解析器的参数,如下所示:
use_cfg = argpr.parse_args(namespace=cfg)
我可以看到我在我的命名空间对象中得到了一个值,因此我希望 ArgumentParser.parse_args 在我的命名空间对象中找到 long_c 但我得到:
argument --long-c/-c is required
我是不是做错了什么?这是错误还是预期的行为?欢迎就如何使这项工作提出任何建议 =)
提前致谢
编辑: - 修正错别字。 - 将命名空间更改为命名空间对象。 - 澄清了我对命名空间对象的使用和我的期望。
Namespace
不是用来传递参数而是用来存储结果的。您需要在 args
参数中传递配置。我认为这就是您所追求的:
cfg = []
if json_dict is not None:
cfg.extend(('-c', json['long-c']))
use_cfg = argpr.parse_args(cfg)
我明白您要做什么,但我认为 argparse
不会按照您希望的方式检查命名空间中的必需参数。通常您不需要提供 namespace
参数,但如果您希望将解析后的参数分配给现有对象,这会很好。
此外,如果您确实想要显式创建一个Namespace
,请务必实例化它:
# use this:
argparse.Namespace()
# not this:
argparse.Namespace
否则,您最终会将属性分配给 Namespace
class 本身。
另请阅读 required
上的注释:
Note: Required options are generally considered bad form because users expect options to be optional, and thus they should be avoided when possible.
您创建和使用命名空间的方式没有任何问题(在您进行更正之后),但正如 André Laszlo 提到的,您的期望是错误的:
...I expect that ArgumentParser.parse_args finds long_c in my Namespace object but I get:
argument --long-c/-c is required
很容易证明 argparse 不是那样工作的:
import argparse as ap
argpr = ap.ArgumentParser()
argpr.add_argument('--long-c', '-c', required=True, dest='long_c')
cfg = ap.Namespace()
print(cfg)
name_space = argpr.parse_args(namespace=cfg)
print(name_space.long_c)
print(name_space) #name_space and cfg are different names for the same object
--output:--
$ python3.4 1.py -c 4
Namespace()
4
Namespace(long_c='4')
(注意,如果你希望存储的值是一个int,那么你可以在add_argument()中加上type=int
)
现在 cfg 命名空间已经具有 long_c
的值:
import argparse as ap
argpr = ap.ArgumentParser()
json_dict = {'long-c': 5}
cfg = ap.Namespace()
if json_dict:
cfg.long_c = json_dict['long-c']
print(cfg)
argpr.add_argument('--long-c', '-c', required=True, dest='long_c')
name_space = argpr.parse_args(namespace=cfg)
print(name_space.long_c)
print(name_space) #name_space and cfg are different names for the same object
--output:--
$ python3.4 1.py -c 4
Namespace(long_c=5)
4
Namespace(long_c='4')
但是...
$ python3.4 1.py
Namespace(long_c=5)
usage: 1.py [-h] --long-c LONG_C
1.py: error: the following arguments are required: --long-c/-c
要得到你想要的行为,你需要使 -c
选项 可选 如果 json_dict 已经有一个值,像这个:
cfg = ap.Namespace()
required = True
if json_dict:
val = json_dict.get('long-c', False)
if val:
cfg.long_c = val
required = False
print(cfg)
argpr.add_argument('--long-c', '-c', required=required, dest='long_c')
我将 ArgumentParser
子类化来做你想让它做的事。
import json
from argparse import ArgumentParser
class ConfigurableArgumentParser(ArgumentParser):
def __init__(self, config_file, *args, **kwargs):
self.config = json.load(config_file)
super(ConfigurableArgumentParser, self).__init__(*args, **kwargs)
def add_argument(self, *args, **kwargs):
store_action = super(ConfigurableArgumentParser, self).add_argument(
*args, **kwargs)
dest = store_action.dest
if dest in self.config:
store_action.default = self.config[dest]
store_action.required = False
return store_action
这个参数解析器接受一个额外的构造函数参数,config_file
它应该是一个指向 JSON 配置文件的文件对象。 add_argument
方法被修改为使用配置文件中的默认值(如果存在),在这种情况下 required
也将设置为 False
.
用法:
if __name__ == '__main__':
from StringIO import StringIO
# config_file = open('my_config.json')
config_file = StringIO('{"long_c": "1"}')
parser = ConfigurableArgumentParser(config_file)
parser.add_argument('--long-c', '-c',
required=True, dest='long_c', type=int)
namespace = parser.parse_args()
print namespace
# Output:
# Namespace(long_c=1)
请注意,类型仍按应有的方式处理,JSON 字符串自动转换为 int
。