0

I have a python app using the multiprocessing library and I'm running into an issue where I expect different processes to create a different instance of a class, however, they are actually creating the same instance of the class. Take this example:

from multiprocessing import Process
from time import sleep


class Foo:
    name = None


def get_foobar():
    return Foo()


class MyProcess(Process):
    def run(self):
        print('process {} running in pid {}'.format(self.name, self.pid))
        my_foo = get_foobar()
        print('got foo {}'.format(id(my_foo)))

        if my_foo.name is None:
            my_foo.name = self.name.upper()

        print("foo's name is {}".format(my_foo.name))

        # do some work
        sleep(3)

        print('process {} running in pid {} done'.format(self.name, self.pid))


for _ in range(2):
    p = MyProcess()
    p.start()

I get the following output:

process MyProcess-1 running in pid 65975
got foo 4322815784
foo's name is MYPROCESS-1
process MyProcess-2 running in pid 65976
got foo 4322815784
foo's name is MYPROCESS-2
process MyProcess-1 running in pid 65975 done
process MyProcess-2 running in pid 65976 done

I was expecting the second process to have a different instance of the class. How is get_foobar() able to return the same instance of Foo to each process?

EDIT / UPDATE: I am running this in python 3.5 on OSX and Ubuntu.

user5038859
  • 133
  • 1
  • 2
  • 11

1 Answers1

1

Basically your answer is here: Why is the id of a Python class not unique when called quickly?

The most relevant quote is:

The id of an object is only guaranteed to be unique during that object's lifetime, not over the entire lifetime of a program.

It seems that your first Foo() instance just "dies" before the second one is created, so they could end up getting the same ID.

Same things happens without multiprocessing:

>>> def run():
...     my_foo = get_foobar()
...     print('got foo {}'.format(id(my_foo))) ... 
>>> run() 
got foo 140690243732040
>>> run() 
got foo 140690243732040

EDIT: This is from the docs:

Return the “identity” of an object. This is an integer which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value.

In this context, the object's existence only within certain scopes (i.e the run function) may mean they have different lifetimes regardless. This is no different from the python 2 docs, but my guess is the implementation is different so that explains the results.

Ofer Sadan
  • 11,391
  • 5
  • 38
  • 62
  • I updated my original post. What's interesting to me is that the id is the same (there's a sleep so the object is not destructed) while both processes are running, however, the attributes can be different which indicates that they are, in fact, different instances of the same class. – user5038859 Jul 07 '17 at 06:03
  • i saw your edit... `get_foobar` has nothing to do with it, same things happens if you do it directly via `my_foo = Foo()` – Ofer Sadan Jul 07 '17 at 06:05
  • Also, I edited my answer again, added some new thoughts – Ofer Sadan Jul 07 '17 at 06:18