Search code examples
pythonobjectmultiprocessingpoolclass-method

Why is my @classmethod variable "not defined"?


I'm currently writing code in Python 2.7, which involves creating an object, in which I have two class methods and other regular methods. I need to use this specific combination of methods because of the larger context of the code I am writing- it's not relevant to this question, so I won't go into depth.

Within my __init__ function, I am creating a Pool (a multiprocessing object). In the creation of that, I call a setup function. This setup function is a @classmethod. I define a few variables in this setup function by using the cls.variablename syntax. As I mentioned, I call this setup function within my init function (inside the Pool creation), so these variables should be getting created, based on what I understand.

Later in my code, I call a few other functions, which eventually leads to me calling another @classmethod within the same object I was talking about earlier (same object as the first @classmethod). Within this @classmethod, I try to access the cls.variables I created in the first @classmethod. However, Python is telling me that my object doesn't have an attribute "cls.variable" (using general names here, obviously my actual names are specific to my code).

ANYWAYS...I realize that's probably pretty confusing. Here's some (very) generalized code example to illustrate the same idea:

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

The error I'm getting when I get to the equivalent of the print cls.A line is this:

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

edit to show usage of this code: The way I'm calling this in my code is as such:

G = General(5)
G.get_results()

So, I'm creating an instance of the object (in which I create the Pool, which calls the setup function), and then calling get_results.

What am I doing wrong?


Solution

  • The reason General.A does not get defined in the main process is that multiprocessing.Pool only runs General._setup in the subprocesses. This means that it will not be called in the main process (where you call Pool).

    You end up with 4 processes where in each of them there is General.A is defined, but not in the main process. You don't actually initialize a Pool like that (see this answer to the question How to use initializer to set up my multiprocess pool?)

    You want an Object Pool which is not natively impemented in Python. There's a Python Implementation of the Object Pool Design Pattern question here on StackOverflow, but you can find a bunch by just searching online.