Why Python pickling library complain about class member that doesn't exist?
<p>I have the following simple class definition:</p>

<pre><code>def apmSimUp(i):
    return APMSim(i)

def simDown(sim):
    sim.close()

class APMSimFixture(TestCase):

    def setUp(self):
        self.pool = multiprocessing.Pool()
        self.sims = self.pool.map(
            apmSimUp,
            range(numCores)
        )

    def tearDown(self):
        self.pool.map(
            simDown,
            self.sims
        )
</code></pre>

<p>Where class APMSim is defined purely by plain simple python primitive types (string, list etc.) the only exception is a static member, which is a multiprocessing manager.list</p>

<p>However, when I try to execute this class, I got the following error information:</p>

<pre><code>Error
Traceback (most recent call last):
  File "/home/peng/git/datapassport/spookystuff/mav/pyspookystuff_test/mav/__init__.py", line 77, in setUp
    range(numCores)
  File "/usr/lib/python2.7/multiprocessing/pool.py", line 251, in map
    return self.map_async(func, iterable, chunksize).get()
  File "/usr/lib/python2.7/multiprocessing/pool.py", line 567, in get
    raise self._value
MaybeEncodingError: Error sending result: '[&lt;pyspookystuff.mav.sim.APMSim object at 0x7f643c4ca8d0&gt;]'. Reason: 'TypeError("can't pickle thread.lock objects",)'
</code></pre>

<p>Which is strange as thread.lock cannot be found anywhere, I strictly avoid  any multithreading component (as you can see, only multiprocessing component is used). And none of these component exist in my class, or only as static member, what should I do to make this class picklable?</p>

<p>BTW, is there a way to exclude a black sheep member from pickling? Like Java's @transient annotation?</p>

<p>Thanks a lot for any help!</p>

<p><strong>UPDATE</strong>: The following is my full APMSim class, please see if you find anything that violates it picklability:</p>

<pre><code>usedINums = mav.manager.list()
class APMSim(object):
    global usedINums

    @staticmethod
    def nextINum():
        port = mav.nextUnused(usedINums, range(0, 254))
        return port

    def __init__(self, iNum):
        # type: (int) -&gt; None

        self.iNum = iNum
        self.args = sitl_args + ['-I' + str(iNum)]

    @staticmethod
    def create():
        index = APMSim.nextINum()
        try:
            result = APMSim(index)
            return result
        except Exception as ee:
            usedINums.remove(index)
            raise

    @lazy
    def _sitl(self):
        sitl = SITL()
        sitl.download('copter', '3.3')
        sitl.launch(self.args, await_ready=True, restart=True)
        print("launching .... ", sitl.p.pid)
        return sitl

    @lazy
    def sitl(self):
        self.setParamAndRelaunch('SYSID_THISMAV', self.iNum + 1)
        return self._sitl

    def _getConnStr(self):
        return tcp_master(self.iNum)

    @lazy
    def connStr(self):
        self.sitl
        return self._getConnStr()

    def setParamAndRelaunch(self, key, value):

        wd = self._sitl.wd
        print("relaunching .... ", self._sitl.p.pid)
        v = connect(self._getConnStr(), wait_ready=True) # if use connStr will trigger cyclic invocation
        v.parameters.set(key, value, wait_ready=True)
        v.close()
        self._sitl.stop()
        self._sitl.launch(self.args, await_ready=True, restart=True, wd=wd, use_saved_data=True)
        v = connect(self._getConnStr(), wait_ready=True)
        # This fn actually rate limits itself to every 2s.
        # Just retry with persistence to get our first param stream.
        v._master.param_fetch_all()
        v.wait_ready()
        actualValue = v._params_map[key]
        assert actualValue == value
        v.close()

    def close(self):

        self._sitl.stop()
        usedINums.remove(self.iNum)
</code></pre>

<p>lazy decorator is from this library:</p>

<p><a href="https://docs.python.org/2/tutorial/classes.html#generator-expressions" rel="nofollow">https://docs.python.org/2/tutorial/classes.html#generator-expressions</a></p>

<p>It would help to see how your class looks, but if it has methods from <code>multiprocessing</code> you may have issues just pickling it by default. Multiprocessing objects can use locks as well, and these are (obviously) unpickle-able.</p>

<p>You can customize pickling with the <a href="https://docs.python.org/dev/library/pickle.html?highlight=pickle#object.__getstate__" rel="nofollow"><code>__getstate__</code></a> method, or <code>__reduce__</code> (documented in the same place).</p>

python serialization pickle