Pickling Python data to Maya attributes
Recently I made the connection that A: It’s really easy to serialize (pickle) data in Python, and B: You can make string attributes on nodes in Maya. It’s not that I was unaware of these topics, it’s just that they’d never occurred in the same mental conversation simultaneously before. But when they did, it was sort of an ‘eureka moment’, and I wrote two functions to make use of this new-found power.
Making use of the cPickle module, I pickle the Python data to a string object and store to a string attr on a Maya node. To retrieve the data, I unpickle the string attributes value back to Python data.
http://docs.python.org/library/pickle.html
http://docs.python.org/library/pickle.html#module-cPickle
import cPickle import maya.cmds as mc def pyToAttr(objAttr, data): """ Write (pickle) Python data to the given Maya obj.attr. This data can later be read back (unpickled) via attrToPy(). Arguments: objAttr : string : a valid object.attribute name in the scene. If the object exists, but the attribute doesn't, the attribute will be added. The if the attribute already exists, it must be of type 'string', so the Python data can be written to it. data : some Python data : Data that will be pickled to the attribute in question. """ obj, attr = objAttr.split('.') # Add the attr if it doesn't exist: if not mc.objExists(objAttr): mc.addAttr(obj, longName=attr, dataType='string') # Make sure it is the correct type before modifing: if mc.getAttr(objAttr, type=True) != 'string': raise Exception("Object '%s' already has an attribute called '%s', but it isn't type 'string'"%(obj,attr)) # Pickle the data and return the coresponding string value: stringData = cPickle.dumps(data) # Make sure attr is unlocked before edit: mc.setAttr(objAttr, edit=True, lock=False) # Set attr to string value: mc.setAttr(objAttr, stringData, type='string') # And lock it for safety: mc.setAttr(objAttr, edit=True, lock=True) def attrToPy(objAttr): """ Take previously stored (pickled) data on a Maya attribute (put there via pyToAttr() ) and read it back (unpickle) to valid Python values. Arguments: objAttr : string : A valid object.attribute name in the scene. And of course, it must have already had valid Python data pickled to it. Return : some Python data : The reconstituted, unpickled Python data. """ # Get the string representation of the pickled data. Maya attrs return # unicode vals, and cPickle wants string, so we convert: stringAttrData = str(mc.getAttr(objAttr)) # Un-pickle the string data: loadedData = cPickle.loads(stringAttrData) return loadedData
And here is some sample usage:
# Make some really special Python data you want to store to a Maya node: specialData = {'red':52, 'green':63.3, 'blue':"ASDF"} print "Python data to store to Maya obj.attr:" print specialData #Python data to store to Maya obj.attr: #{'blue': 'ASDF', 'green': 63.299999999999997, 'red': 52} # Define our node and attr name based on the selected object: node = mc.ls(selection=True)[0] objAttr = '%s.pyPickle'%node # Store data to our node: pyToAttr(objAttr, specialData) # Later, get data back: storedData = attrToPy(objAttr) print "Restored Python Data:" print storedData #Restored Python Data: #{'blue': 'ASDF', 'green': 63.299999999999997, 'red': 52}