I am writing a grid searching utility and am trying to use multiprocessing to speed up calculation. I have an objective function which interacts with a large class which I cannot pickle due to memory constraints (I can only pickle relevant attributes of the class).
import pickle
from multiprocessing import Pool
class TestClass:
    def __init__(self):
        self.param = 10
    def __getstate__(self):
        raise RuntimeError("don't you dare pickle me!")
    def __setstate__(self, state):
        raise RuntimeError("don't you dare pickle me!")
    def loss(self, ext_param):
        return self.param*ext_param
if __name__ == '__main__':
    test_instance = TestClass()
    def objective_function(param):
        return test_instance.loss(param)
    with Pool(4) as p:
        result = p.map(objective_function, range(20))
    print(result)
In the following toy example, I was expecting during pickling of the objective_function, that test_instance would also have to be pickled, thus throwing RuntimeError (due to exception throwing at __getstate__). However this does not happen and the code runs smoothly.
So my question is - what is being pickled here exactly? And if test_instance is not pickled, then how is it reconstructed on individual processes?