【问题标题】:How do I wrap argparse options into the python class?如何将 argparse 选项包装到 python 类中?
【发布时间】:2018-03-26 23:19:00
【问题描述】:

我对 python OOP 还很陌生,所以我有些困惑。

目前我有:

parser = argparse.ArgumentParser(description='script 1.0')
parser.add_argument('-a', '--foo', help='specify foo')
parser.add_argument('-b', '--bar', type=int, help='specify bar')
parser.add_argument('-c', '--baz', help='specify baz')
parser.add_argument('-d', '--bar2', help='bar2')

args = parser.parse_args()

foo = args.foo
bar = args.bar
baz = args.baz
bar2 = args.bar2

效果很好,但我想为我的整个脚本创建一个类,并将 argparse 作为一个类的方法(有可能吗?)。

所以我尝试了:

     import argparse
         ....

        Class Program:
             def __init__(self, foo, bar, baz, bar2):
                 self.foo = foo
                 self.bar = bar
                ...(so on for each arg)
             def main():
                 parser = argparse.ArgumentParser(description='script 1.0')
                 parser.add_argument('-a', '--foo', help='specify foo')
                 parser.add_argument('-b', '--bar', type=int, help='specify bar')
                 parser.add_argument('-c', '--baz', help='specify baz')
                 parser.add_argument('-d', '--bar2', help='bar2')

                 args = parser.parse_args()

                 foo = self.foo
                 bar = self.bar
                 baz = self.baz
                 bar2 = self.bar2

不过,我认为我做得不对。我没有找到太多关于它的信息,但是关于 SO 的一篇帖子并没有向我澄清情况,所以我想对我的具体情况发表意见

【问题讨论】:

  • 您似乎走在了正确的轨道上,您实际上面临什么问题?
  • @ZdaR,argparse 选项没有被记住以供进一步使用,我大约,我不应该像这样初始化类:__init__(self, --foo, --bar, --baz, --bar2)
  • 我认为最好有明确的关注点分离。换句话说,将 CLI 输入与业务逻辑(程序类)分开。为此,我只会在您的脚本直接执行时使用 argparse。换句话说,在if __name__ == __main__ 部分下。然后一旦 argparse 完成它的工作,创建一个类实例,将解析的参数传递给它,并运行你的逻辑。
  • 编写好的 OOP 并不意味着所有东西都需要在一个类中。让你的班级做一件事情也很重要。正如单一职责原则所述。

标签: python class parameter-passing argparse


【解决方案1】:

argparse 已经使用了类。 argparse.ArgumentParser(...) 创建一个解析器对象。 parser.add_argument(...) 创建一个 Action 对象,并将其放入 parser 列表中。它还将它返回到您的代码中,这在某些高级用途中可能很方便。 parse_args() 返回一个 argparse.Namespace 对象。

您可以子类化argparse 类来自定义它们的性能。

但通常您不需要创建自己的 parser 类 - 除非您需要很多特殊行为。

这是我认为干净地使用argparse

import argparse

# your code
def main(args):
    foo = args.foo
    # other uses of args

def other(foo, bar):
    # code using values

def make_parser():
    parser = argparse.ArgumentParser(description='script 1.0')
    parser.add_argument('-a', '--foo', help='specify foo')
    parser.add_argument('-b', '--bar', type=int, help='specify bar')
    parser.add_argument('-c', '--baz', help='specify baz')
    parser.add_argument('-d', '--bar2', help='bar2')
    return parser

if __name__ == '__main__':
    parser = make_parser()
    args = parser.parse_args()

将解析器定义包装在一个函数中是个好主意。在更复杂的情况下,它可能是一个类。但通常每个脚本只需要一个解析器,所以一个函数就足够了。该函数可以在脚本的主体中,但实际使用应该在if __name__块中,这样脚本就可以在不使用解析器的情况下导入。

这会将args 命名空间置于全局环境中,您的所有代码都可以访问该命名空间。它可以传递给您的函数,也可以传递选定的值:

main(args)
other(args.foo, args.bar)
foo = args.foo
do_things3(foo)
d = vars(args) # args in dictionary form

编写代码是个好主意,这样它就可以作为导入的类和/或函数运行,并且可以作为脚本运行。 argparse 部分在作为脚本运行时设置值。导入时,导入脚本设置必要的控制值,可能带有自己的parser

【讨论】:

    【解决方案2】:

    我会这样做:

    import argparse
    
    
    Class Program:
        def __init__(self, foo, bar, baz, bar2):
            self.foo = foo
            self.bar = bar
            ...(so on for each arg)
        
        def do_things():
            pass
    
             
    def get_args():
        parser = argparse.ArgumentParser(description='script 1.0')
        parser.add_argument('-a', '--foo', help='specify foo')
        parser.add_argument('-b', '--bar', type=int, help='specify bar')
        parser.add_argument('-c', '--baz', help='specify baz')
        parser.add_argument('-d', '--bar2', help='bar2')
    
        return parser.parse_args()
    
    
    def main(args):
        instance = Program(args.foo,
                           args.bar, 
                           args.baz, 
                           args.bar2)
    
        instance.do_things()
    
    
    if __name__ == '__main__':
        args = get_args()
        main(args)
    

    说明: 试着把东西分开... 解析参数在get_args 函数中完成,然后将“args”传递给主函数。 main函数负责通过args传递的参数初始化对象并对对象执行一些工作。

    【讨论】:

      猜你喜欢
      • 2016-03-24
      • 2011-08-01
      • 2011-06-05
      • 2016-08-11
      • 2013-07-06
      • 1970-01-01
      • 2017-03-12
      • 2013-12-21
      • 2017-05-24
      相关资源
      最近更新 更多