在Python中从命名空间获取所需选项

在Python中从命名空间获取所需选项,python,argparse,Python,Argparse,我创建了一个ArgumentParser,如下所示: argpr = ArgumentParser() argpr.add_argument('--long-c', '-c', required=True, dest='long_c') use_cfg = argpr.parse_args(namespace=cfg) cfg = ap.Namespace() required = True if json_dict: val = json_dict.get('long-c',

我创建了一个ArgumentParser,如下所示:

argpr = ArgumentParser()
argpr.add_argument('--long-c', '-c', required=True, dest='long_c') 
use_cfg = argpr.parse_args(namespace=cfg)
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')
如果存在json配置文件,我会将配置添加到命名空间:

cfg = argparse.Namespace()
if json_dict is not None:
    cfg.long_c = json['long-c']
print vars(cfg)
然后我使用名称空间作为参数解析器的参数,如下所示:

argpr = ArgumentParser()
argpr.add_argument('--long-c', '-c', required=True, dest='long_c') 
use_cfg = argpr.parse_args(namespace=cfg)
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.parse_args在我的名称空间对象中找到long_c,但我得到:

argument --long-c/-c is required
argument --long-c/-c is required
我做错什么了吗?这是一个bug还是预期的行为?欢迎对如何使此工作正常进行提出任何建议=)

先谢谢你

编辑: -修正了打字错误。 -已将命名空间更改为命名空间对象。 -阐明了我对名称空间对象的使用和我的期望

s不是用于传递参数,而是用于存储结果。您需要在
args
参数中传递配置。我想这就是你想要的:

cfg = []
if json_dict is not None:
    cfg.extend(('-c', json['long-c']))
use_cfg = argpr.parse_args(cfg)
我知道您试图做什么,但我不认为
argparse
会以您希望的方式检查名称空间中所需的参数。通常,您不需要给出
名称空间
参数,但如果希望将解析后的参数分配给现有对象,则可以这样做

此外,如果确实要显式创建
命名空间
,请确保实例化它:

# use this:
argparse.Namespace()
# not this:
argparse.Namespace
否则,您将最终为
名称空间
类本身分配属性

另请阅读以下说明:

注:所需选项通常被认为是不好的形式,因为用户 期望选项是可选的,因此在 可能


您创建和使用名称空间的方式(在进行更正之后)没有任何问题,但正如AndréLaszlo所提到的,您的期望是错误的:

…我希望ArgumentParser.parse_args在我的 命名空间对象,但我得到:

argument --long-c/-c is required
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,则可以添加
type=int
以添加_参数()

现在cfg名称空间已经有了
long\u 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
要获得所需的行为,如果json dict已经有值,则需要将
-c
选项设置为可选,如下所示:

argpr = ArgumentParser()
argpr.add_argument('--long-c', '-c', required=True, dest='long_c') 
use_cfg = argpr.parse_args(namespace=cfg)
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\u file
,该参数应该是指向JSON配置文件的文件对象。
add_参数
方法被修改为使用配置文件中的默认值(如果存在),在这种情况下,
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

您的代码中是否有相同的
argparese
打字错误,或者这只是您的问题?@AndréLaszlo。。。“对不起,更正了。”齐达思,我为什么要这么做?我希望我的参数来自comandline,我希望parse_args在我提供的名称空间对象中找到值。像这样使用
Namespace
参数相当于指定默认值。请在没有“required=True”的情况下尝试它。我有argparse.Namespace()。。。又是打字错误。谢谢您的回答。请注意,add_argument()方法不会返回任何内容。