【问题标题】:Pattern to handle both command line arguments and/or api method parameters处理命令行参数和/或 api 方法参数的模式
【发布时间】:2016-02-28 19:35:35
【问题描述】:

我正在尝试设置一个代码,该代码可以通过带有命令行参数的命令行运行,或者可以从 python 脚本或交互式会话中调用——带有传递的参数。有什么好的模式/方法可以做到这一点?

我现在使用的基本思路是:

from argparse import ArgumentParser


class Sets:
    def __init__(self):
        self.verbose = False
        self.par = 1
        self.args = ['run', 'test']

    def _update(self, parsed):
        for key in vars(parsed).keys():
            setattr(self, key, getattr(parsed, key))
            print("\t", getattr(self, key))


def main(**kwargs):
    sets = _parseArgs()
    for key in kwargs.keys():
        setattr(sets, key, kwargs[key])

    print("verbose = ", sets.verbose)
    print("par = ", sets.par)
    print("args = ", sets.args)

    return


def _parseArgs():
    sets = Sets()
    pars = ArgumentParser()
    pars.add_argument('--verbose', action='store_true', default=sets.verbose)
    pars.add_argument('--par', nargs=1, type=int, default=sets.par)
    pars.add_argument('--args', nargs='+', type=str, default=sets.args)
    sets._update(pars.parse_args())
    return sets


if __name__ == "__main__":
    main()

不过好像有点绕……

【问题讨论】:

  • 您打算如何在会话或脚本中使用它?
  • @hpaulj 如果我正确理解了术语:两者都 --- 交互式/作为导入函数和可执行脚本。

标签: python api command-line-arguments argparse


【解决方案1】:

您的Sets 课程似乎没问题,但我还没有测试过。但我认为,它比你需要的更复杂。将main 调用放在if __name__ 块中是正确的。有时解析器也在那里定义,但这不是必需的。

只要参数名称正常,您就可以将值作为属性访问。

 args = parser.parse_args()
 print("verbose = ", args.verbose)
 print("par = ", args.par)
 print("args = ", args.args)

您可以使用以下方法构建自己的 args 对象:

args = argparse.Namespace(verbose=False, par=1, args=['run', 'test'])

事实上你可以把它传递给解析器:

args = parser.parse_args(namespace=args)

您可以替换自己的“命令行”列表

args = parser.parse_args(['--verbose','--par','2'])

我在测试解析器代码时经常使用这种格式。

对了,你真的要parnargs=1吗?默认的nargs 采用一个参数。 nargs=1 做同样的事情,但在命名空间中创建一个列表 pars=[1]

dd = vars(args)

您可以使用所有正常的字典操作。例如:

dd0 = dict(pars=3, verbose=False)
dd0.update(vars(args))

虽然如果dd0 包含与解析器相同的键,这并没有什么意义。 args 将始终具有这些值,无论是默认值还是来自命令行。

另一种选择是在函数中定义关键字参数。

def myaction(verbose=False, pars=1, args=None, **kwargs): # 用这些做点什么 print(verbose, pars, args, kwargs)

用途:

myaction(**vars(args))
myaction(pars=2, args=[12,34], extra='for kwargs')
myaction(**{'pars':3})

【讨论】:

  • 谢谢,这里有一些非常有用的东西!我省略了main 定义中的命名变量,因为它只是另一个必须重写它们的地方(除了add_arguments 和Sets)。我确实看到 Sets 对象是多余的。
【解决方案2】:
from argparse import ArgumentParser


def main(**kwargs):
    print(kwargs)


if __name__ == "__main__":
    pars = ArgumentParser()
    pars.add_argument('--verbose', action='store_true')
    pars.add_argument('--par', nargs=1, type=int, default=1)
    pars.add_argument('--args', nargs='+', type=str, default=['run', 'test'])

    main(**vars(pars.parse_args()))

输出:

{'par': 1, 'args': ['run', 'test'], 'verbose': False}

或者:

from argparse import ArgumentParser


def main(args):
    print(args)


if __name__ == "__main__":
    pars = ArgumentParser()
    pars.add_argument('--verbose', action='store_true')
    pars.add_argument('--par', nargs=1, type=int, default=1)
    pars.add_argument('--args', nargs='+', type=str, default=['run', 'test'])

    main(pars.parse_args())

哪些输出:

Namespace(args=['run', 'test'], par=1, verbose=False)

...但您可以更轻松地访问它,即args.argsargs.parargs.verbose

【讨论】:

  • 这里不需要dictdict(vars(...))vars() 返回一个字典。
  • 谢谢!这绝对是清洁的一大步——Sets 对象应该更明显是多余的......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-13
  • 2015-05-01
  • 1970-01-01
  • 2013-05-08
  • 1970-01-01
  • 2010-09-08
相关资源
最近更新 更多