【问题标题】:Why is my @classmethod variable "not defined"?为什么我的@classmethod 变量“未定义”?
【发布时间】:2016-07-27 16:51:51
【问题描述】:

我目前正在使用 Python 2.7 编写代码,其中涉及创建一个对象,其中我有两个类方法和其他常规方法。我需要使用这种特定的方法组合,因为我正在编写的代码的上下文更大——它与这个问题无关,所以我不会深入探讨。

在我的 __init__ 函数中,我正在创建一个池(一个多处理对象)。在创建它时,我调用了一个设置函数。这个设置函数是一个@classmethod。我使用 cls.variablename 语法在此设置函数中定义了一些变量。正如我所提到的,我在我的 init 函数中(在 Pool 创建中)调用了这个 setup 函数,因此应该根据我的理解创建这些变量。

稍后在我的代码中,我调用了一些其他函数,这最终导致我在我之前谈到的同一个对象(与第一个 @classmethod 相同的对象)中调用另一个 @classmethod。在这个@classmethod 中,我尝试访问我在第一个@classmethod 中创建的cls.variables。但是,Python 告诉我我的对象没有属性“cls.variable”(这里使用通用名称,显然我的实际名称是特定于我的代码的)。

无论如何...我意识到这可能很令人困惑。下面是一些(非常)通用的代码示例来说明相同的想法:

class General(object):
    def __init__(self, A):
        # this is correct syntax based on the resources I'm using,
        # so the format of argument isn't the issue, in case anyone
        # initially thinks that's the issue
        self.pool = Pool(processes = 4, initializer=self._setup, initargs= (A, )

    @classmethod
    def _setup(cls, A):
        cls.A = A

    #leaving out other functions here that are NOT class methods, just regular methods

    @classmethod
    def get_results(cls):
        print cls.A

当我到达 print cls.A line 时遇到的错误是这样的:

AttributeError: type object 'General' has no attribute 'A'

编辑以显示此代码的用法: 我在代码中调用它的方式是这样的:

G = General(5)
G.get_results()

所以,我正在创建对象的一个​​实例(我在其中创建了调用 setup 函数的 Pool),然后调用 get_results。

我做错了什么?

【问题讨论】:

  • 你打过General._setup吗?
  • 特别是,你有没有在调用General.get_results的过程中调用General._setup
  • @chepner 我在初始化函数中创建 Pool 对象时调用它。
  • @user2357112 同上^
  • “我在我的初始化函数中调用了这个设置函数”——不,你没有。

标签: python object multiprocessing pool class-method


【解决方案1】:

General.A 没有在主进程中定义的原因是multiprocessing.Pool 只在 进程中运行 General._setup。这意味着它不会在主进程(您调用Pool)中被调用。

您最终会得到 4 个进程,其中每个进程都定义了 General.A,但在主进程中没有。您实际上并没有像那样初始化 Pool(请参阅this answer 问题How to use initializer to set up my multiprocess pool?

你想要一个Object Pool,它不是在 Python 中原生实现的。 StackOverflow 上有一个Python Implementation of the Object Pool Design Pattern 的问题,但是你可以通过在线搜索找到一堆。

【讨论】:

  • @Ria 您可能缺少某些功能。该网站说有一个独立的 repo 可用here
  • @Ria:是的,你搞错了。该链接中的示例从不尝试从主进程访问池 initializer 中设置的任何内容,因为该初始化从未在主进程中发生。
  • @Artyer 感谢您的帮助。我在代码示例中遗漏了很多函数,因为我认为它们只会让事情变得更加混乱,所以我确实认为我的实际代码中都有它们。但很可能我错过了一些东西。再次感谢!
  • @user2357112 链接中的示例不是在 get_results 函数中调用 cls.session 和 cls.prepared 吗?而这些变量是在 setup 函数中设置的。
  • @Ria:仅在单进程版本中。多进程版本确保永远不会这样做。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-13
相关资源
最近更新 更多