如何将argparse参数传递给一个类

29
我是一名编程新手,尤其是对Python不熟悉。我正在尝试学习如何将我创建的argparse参数传递到类中以正确/推荐的方式使用。除了学习Python外,我还在努力学习以面向对象的方式进行操作,以便更轻松地学习其他面向对象类型的语言。
以下是我尝试做的示例:
import argparse

class passyourcliargstome():
    def __init__(self, whatdoiputheretogetmycliargs):
        #how do I get my cli args here?
        pass
    def otherfunctionsthatdothings():
        pass

if __name__ == '__main__':
    #grab the arguments when the script is ran
    parser = argparse.ArgumentParser(
         description='Make things happen.')
    parser.add_argument('-f', '--foo', action='store_true', default=False, help='here be dragons')
    parser.add_argument('-b', '--bar', action='store_true', default=False, help='here be more dragons')

    passyourcliargstome.otherfunctionsthatdothings()

因此,我正在主类外定义argparse参数,并想知道如何在类内部获取它们。这是正确的方式吗?我应该只是将argparse作为我的类下的一个函数吗?
非常感谢您提前提供的任何帮助、参考等。
注:由于我没有足够的声望来回答自己的问题,这是我发布适当答案的唯一途径。
好的,我花了一些时间,但我设法把它拼凑起来了。RyPeck的答案帮助我获得了我的参数(我的代码中缺少的东西),但之后我在尝试测试代码时遇到了未绑定方法错误。我不知道那是什么意思。我有提到过我符合我的屏幕名称吗?
直到我找到并阅读了这个,它才真正点击这里。这是我的工作代码。如果有人对此有任何补充,包括“你还是做错了,要用这种方式,正确的方式。”我全都听着。同时,感谢您的帮助。
import argparse

class Passyourcliargstome(object):

    def __init__(self):
        #here's how I got my args here
        self.foo = args.foo
        self.bar = args.bar
    def otherfunctionsthatdothings(self):
        print "args inside of the main class:"
        print self.foo
        print self.bar

if __name__ == '__main__':
    #grab the arguments when the script is ran
    parser = argparse.ArgumentParser(description='Make things happen.')
    parser.add_argument('-f', '--foo', action='store_true', default=False, help='here be dragons')
    parser.add_argument('-b', '--bar', action='store_true', default=False, help='here be more dragons')

    args = parser.parse_args()
    print "args outside of main:"
    print args.foo
    print args.bar

    #this was the part that I wasn't doing, creating an instance of my class.
    shell = Passyourcliargstome()
    shell.otherfunctionsthatdothings()

在没有参数的情况下运行此代码会输出四次False。两次是在类实例之外,另外两次是在类实例内部。

5
我更倾向于将 args 作为参数传递给类的 __init__ 方法,而不是依赖于它是一个全局变量。 - hpaulj
3个回答

35

使用 parser.parse_args 并将其包装在 vars 中,将特殊的 argparse Namespace 类型转换为常规的 Python 字典。通常情况下,您需要此模式:

def main():
  parser = argparse.ArgumentParser()
  parser.add_argument('foo')
  parser.add_argument('bar')
  args = parser.parse_args()
  args_dict = vars(args)

之后,您可以将参数显式地传递给任何接受它的类或函数,也可以一次性全部传递。对于一个类,最好显式地写出所需的参数。像这样:

class MyClass(object):
  def __init__(self, foo, bar):
    self.foo = foo
    self.bar = bar

  def Print(self):
    print self.foo
    print self.bar

现在,您可以将这两者结合起来,如下所示:

import argparse

class MyClass(object):
  def __init__(self, foo, bar):
    self.foo = foo
    self.bar = bar

  def Print(self):
    print self.foo
    print self.bar

def main():
  parser = argparse.ArgumentParser()
  parser.add_argument('foo')
  parser.add_argument('bar')
  args = parser.parse_args()
  c1 = MyClass(args.foo, args.bar)
  args_dict = vars(args)
  c2 = MyClass(**args_dict)

会创建c1c2,但最好明确地创建类,就像使用c1一样。


1
为什么明确编写所需的参数是最好的?我发现不这样做更加简洁 -- 添加了相当多的样板代码。 - ijoseph
2
@ijoseph 我想这只是个人偏好。我之所以说“最佳”是为了可维护性的原因,一般来说,其他人阅读你的类(可能要扩展它)时,如果它们被明确地写出来,而不是使用*kwargs、args、setattr()等花哨的元处理方式,那么他们会更容易看到它的功能和如何避免破坏它。这不是一个硬性规定。请根据实际情况判断。 - Dave

13
SimpleParsing做得相当不错。
from simple_parsing import parse
from dataclasses import dataclass


@dataclass
class ExecCfg:
    src_dir: str          # source directory name
    num_files: int = -1   # max number of files, -1 for all
    debug: bool = False   # add debug plots

args = parse(ExecCfg)

~ % python dataclass_args.py -h 
usage: dataclass_args.py [-h]
--src_dir str [--num_files int] [--debug bool]

options:   -h, --help            show this help message and exit

ExecCfg ['config']:   ExecCfg(src_dir: str, num_files: int = -1, debug: bool = False)

  --src_dir str         source directory name (default: None)  
--num_files int       max number of files, -1 for all (default: -1)   --debug bool, --nodebug bool
                        add debug plots (default: False)

2
在添加参数后,您需要执行以下操作。
args = parser.parse_args()

如果您在args上执行打印操作,您会发现所有参数都在一个命名空间参数中。
然后,您可以像这样访问它们 -
print args.foo
print args.bar

从那里开始,你可以像普通变量一样处理它们。请参阅argparse文档以获取更详细的信息。


我应该在类的init函数内部执行args = parser.parse_args(),还是完全在类外部执行? - some_noob
在类外,你可以将参数传递给类。你需要在主函数中解析所有的参数。花些时间阅读文档,它会为你澄清一切。 - RyPeck
有一天我会回头看这个并笑出声来。所以你是在告诉我变量args在类声明中被传递了吗?因此: class passyourcliargstome(): 将变成: class passyourcliargstome(object, args): - some_noob
阅读有关类的内容。通过注释来解释它并不容易。http://docs.python.org/2/tutorial/classes.html - RyPeck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接