When I try to save a ROOT object using shelve, it panics and fails. This started happening after I brought my local build up-to-date with the master branch–I am not sure what changes caused the problem. Reproducer follows. Output attached.
import shelve
import ROOT
df = ROOT.RDataFrame(10).Define('e', 'rdfentry_')
h = df.Histo1D('e')
shelf = shelve.open('test', 'n')
shelf['h'] = h
ROOT Version: master
Platform: macOS
Compiler: Not Provided
output.txt (19.8 KB)
Hi,
at what commit was your local build before? Recently, for some definition of recently, ROOT master has switched to a completely new version of PyROOT. My first guess would be that. You can see if switching -Dpyroot_experimental=OFF when building fixes the problem, if yes, that’s it, and I guess you should open a jira ticket.
Cheers,
Enrico
Unfortunately, setting that flag appears to break pyROOT completely:
In [1]: import ROOT
---------------------------------------------------------------------------
ImportError Traceback (most recent call last)
<ipython-input-1-ee8dc4376aa8> in <module>()
----> 1 import ROOT
/Applications/root_build/lib/ROOT.py in <module>()
22 ### system and interpreter setup ------------------------------------------------
23 import os, sys, types
---> 24 import cppyy
25
26 ## there's no version_info in 1.5.2
/Applications/root_build/lib/cppyy.py in <module>()
59 sys.setdlopenflags( 0x100 | 0x2 ) # RTLD_GLOBAL | RTLD_NOW
60
---> 61 import libPyROOT as _backend
62
63 # reset dl flags if needed
ImportError: dlopen(/Applications/root_build/lib/libPyROOT.so, 2): Library not loaded: @rpath/Python3.framework/Versions/3.7/Python3
Referenced from: /Applications/root_build/lib/libPyROOT.so
Reason: image not found
Total build command:
cmake -Dall=On -Dimt=On -DPYTHON_EXECUTABLE=/Users/michael/anaconda2/bin/python2.7 -DPYTHON_INCLUDE_DIR=/Users/michael/anaconda2/include/python2.7/ -DPYTHON_LIBRARY=/Users/michael/anaconda2/lib/libpython2.7.dylib -Dpyroot_experimental=OFF ../root/ && make
Build log attached.
build_log.txt (856.3 KB)
Well – time to hand this off to PyROOT expert @etejedor 
Hi,
The regular pickling works in master with the new PyROOT:
>>> import ROOT, pickle
>>> h = ROOT.TH1D()
>>> pickle.dumps ( h )
b'\x80\x03clibROOTPythonizations3_7\n_CPPInstance__expand__\nq\x00B1\x02\x00\x00@\x00\x02-\xff\xff\xff\xffTH1D\x00@\x00\x02 \x00\x03@\x00\x01\xfe\x00\x08@\x00\x00\x0e\x00\x01\x00\x01\x00\x00\x00\x00\x03\x00\x00\...'
From what I see in the error stack you sent, shelve uses cPickle:
[/Users/michael/anaconda2/lib/python2.7/lib-dynload/cPickle.so] save (no debug info)
[/Users/michael/anaconda2/lib/python2.7/lib-dynload/cPickle.so] Pickler_dump (no debug info)
If I try the code above the cPickle instead of pickle it also works.
I don’t know how exactly shelve uses cPickle to trigger that error. Do you know what are the requirements of shelve with respect to the objects to be “shelved”?
Hi, @etejedor,
So it turns out the problem is just with pickling RDF pointers, not TH1D. So, adjusting the reproducer above,
import shelve
import ROOT
df = ROOT.RDataFrame(10).Define('e', 'rdfentry_')
h = df.Histo1D('e')
h_ = h.GetPtr()
shelf = shelve.open('test', 'n')
shelf['h'] = h_
shelf.close()
works, but
shelf['h'] = h
does not. Since this is a pointer to a non-pickled ROOT object, perhaps this behavior is expected.
Hi @mwilkins ,
Yes, indeed you found the reason. We can’t serialize RResultPtrs (which is what e.g. Histo1D returns) because they contain a shared pointer to the underlying object, and we can’t serialize shared pointers at the moment.
You can also use GetValue to get the underlying object and shelve that.