如何将 argparse 参数传递给类

Posted

技术标签:

【中文标题】如何将 argparse 参数传递给类【英文标题】:how to pass argparse arguments to a class 【发布时间】:2013-11-30 01:30:42 【问题描述】:

我对一般编码特别是 Python 非常陌生。我正在尝试学习如何将我创建的 argparse 参数传递到一个类中以使用正确/推荐的方式。除了学习 python,我还在尝试学习如何以 OOP 方式做事,以便学习其他 OOP 类型的语言更容易一些。

所以这是我正在尝试做的一个示例:

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 在我的班级下成为一个函数吗?

提前感谢您的任何帮助、参考等。

编辑:11/16 2:18 EST

注意:由于我没有足够的代表来回答我自己的问题,这是我发布正确答案的唯一途径。

好的,我花了一些时间,但我设法把它拼凑起来。 RyPeck 的回答帮助我获得了我的论点(我的代码丢失了一些东西),但后来当我尝试测试代码时,我遇到了未绑定的方法错误。我不知道那是什么意思。我有没有提到我辜负了我的网名?

在我找到并阅读this 之前,它并没有真正点击。这是我的工作代码。如果有人对此有任何补充,包括“你仍然做错了,这样做,正确的方式”。我全是耳朵。同时,感谢您的帮助。

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 四次。两次在类实例外,两次在类实例内。

【问题讨论】:

我更愿意将 args 作为参数传递给 __init__ 类,而不是依赖于它是一个全局变量。 【参考方案1】:

使用parser.parse_args 并用vars 包装它,将特殊的argparse Namespace 类型转换为常规的Python dict。一般来说,您需要这种模式:

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 所做的那样。

【讨论】:

为什么最好明确地编写所需的参数?我发现不这样做会更干净——添加了相当多的样板代码。 @ijoseph 我想这只是偏好。出于可维护性的原因,我说“最好”,因为一般来说,其他人阅读您的课程(可能会扩展它)将更容易看到它的作用以及如果它们被明确写出如何不破坏事物,而不是花哨使用 **kwargs、*args、setattr() 等进行元处理。这不是硬性规定。使用您的最佳判断。【参考方案2】:

一个简单的for 循环可以传递参数(或设置你的属性):

    args_dict = vars(self.parser.parse_args())
    # using argparse arguments as attributes of this (self) class
    for item in args_dict:
        setattr(self, item, args_dict[item])

但是...也许优雅的方法是使用 argparse 初始化您的类,并通过命名空间将它们直接设置为类:

  class Foo:
  def __init__(self)
      self.parser = ArgumentParser()
      self.parser.add_argument('-f', '--foo, default=False, action='store_true', help='foo or not?')
      self.parser.add_argument('-b', '--bar', default=0, action='store', help='set the bar')  
      self.parser.parse_args(namespace=self)

一个空输入相当于:

  class Foo:
  def __init__(self)
      self.foo = False
      self.bar = 0

【讨论】:

【参考方案3】:

添加参数后,您必须执行以下操作。

args = parser.parse_args()

如果您在 args 上进行打印,您会看到您在命名空间参数中拥有所有参数。

然后您可以像这样访问它们 -

print args.foo
print args.bar

从那里,您可以将它们视为普通变量。有关更多详细信息和更多信息,请参阅argparse documentation。

【讨论】:

我是在类初始化函数内部还是完全在类外部执行 args = parser.parse_args()? 课外。然后,您可以将 args 传递给该类。您想在 main.xml 中解析所有参数。花一些时间查看文档,它会为您解决所有问题。 有一天我会回过头来笑一笑。所以你告诉我变量 args 是在类声明中传递的?所以:class passyourcliargstome(): 会变成:class passyourcliargstome(object, args): 阅读课程。通过 cmets 解释它并不容易。 docs.python.org/2/tutorial/classes.html

以上是关于如何将 argparse 参数传递给类的主要内容,如果未能解决你的问题,请参考以下文章

将参数传递给 Docker 容器中的 Python argparse

如何使用 argparse 将列表作为命令行参数传递?

在 AzureML 中部署模型时如何将参数传递给评分文件

从 subprocess.Popen 将参数传递给 argparse

使用 argparse 将 Shell 参数传递给 Boto3 Python

如何将子类作为期望基类的函数的参数传递,然后将该对象传递给指向这些抽象类对象的指针向量?