Error pickling Prophet objects in Python 3.6.
arnaudvl opened this issue · comments
Attempting to pickle a Prophet object in Python 3.6 (3.6.10 to be precise) results in the following error:
TypeError: can't pickle _thread.RLock objects
Snippet to reproduce the error:
from fbprophet import Prophet
import pickle
with open('test.pickle', 'wb') as f:
pickle.dump(Prophet(), f)
Trying to save with dill also does not help. The error does not occur in Python 3.7.
I'm seeing the same behavior
- Centos 7
yum install centos-release-scl
yum-config-manager --enable rhel-server-rhscl-7-rpms
yum install devtoolset-7
scl enable devtoolset-7 bash
- Python 3.6.9
- gcc version 4.8.5
- pystan-2.19.1.1
- fbprophet-0.6
>>> import pickle
>>> with open("foo.pkl", "wb") as f:
... pickle.dump(m, f)
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
TypeError: can't pickle _thread.RLock objects`
I was able to reproduce this. It happens in fbprophet==0.6 but not fbprophet==0.5. v0.6 changed the Stan interface to enable using cmdstanpy, and this refactoring seems to be the source of the issue. There is now a class PyStanBackend:
prophet/python/fbprophet/models.py
Line 198 in 952b544
an instance of which is attached to the Prophet object:
prophet/python/fbprophet/forecaster.py
Line 152 in 952b544
That is the object that cannot be pickled:
import logging
from fbprophet.models import PyStanBackend
logger = logging.getLogger('fbprophet')
b = PyStanBackend(logger=logger)
with open('test.pickle', 'wb') as f:
pickle.dump(b, f) # FAILS with error
The issue is that the stan backends are storing the logger as an attribute:
prophet/python/fbprophet/models.py
Line 21 in 952b544
and you can't pickle loggers. So this works to pickle the backend.
b.logger = None
with open('test.pickle', 'wb') as f:
pickle.dump(b, f) # WORKS
Workaround:
Wipe the stan backend logger object prior to pickling.
m = Prophet()
m.stan_backend.logger = None
with open('test.pickle', 'wb') as f:
pickle.dump(m, f)
(Or, of course, upgrading to Py 3.7 is a workaround, for those for whom this is possible).
The fix:
I can't think of any reason why the logger would need to be stored on the backend, so we can just remove that and instead use a logger defined in that file, something like fbprophet.models
as is done for plotting here:
prophet/python/fbprophet/plot.py
Line 16 in 952b544
Built-in json serialization is now pushed out in v0.7 and should be used instead of pickle as described here: https://facebook.github.io/prophet/docs/additional_topics.html#saving-models