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}
Arduino talks to Processing, Python...
Sparse posting...
  • Trackback are closed
  • Comments (10)
  1. Are you aware of cPickle.dumps() and cPickle.loads() ?

    ie,

    maya.cmds.setAttr(‘my_node.some_str_attr’,cPickle.dumps(my_python_obj))

  2. Thanks for the tip, that’s good info. I’ve updated by code above. I was so excited with my idea I failed to read through any more of the pickle docs than I needed. And I wasted a lot of time fiddling with the StringIO objects… Always a more elegant way it seems :)

  3. This just dawned on me this morning and I went searching the web. Lo and behold another person is doing it! I’m building a level editor inside Maya and this is an integral part of it.

  4. nice! Funny bit is I’ve barely used it once I figured it out. But at least I have it in my toolbox now 😉 Good luck.

    • mclavan
    • October 26th, 2010 8:43am

    It seems so obvious. Thank you so much for sharing.

  5. I was just reading up on pickling this morning to store things to a text file, and then I found this post. Great stuff!

    I imagine you could mix these ideas with the OOP ideas in this article http://www.macaronikazoo.com/?p=752 to store things like functions on a node’s attribute!

    Then, for example, you could conceivably store a dictionary of functions like IK_FK_seamless_switch() on every rig control that supports that functionality, as a cPickle.dumps().

    Have you tried this? What other implementations have you used pickle for?

  6. MacaroniKazoo does some great stuff, for sure 😉 I’ve still barely used this tech since I authored it, but I could see using it to script data on a node that could be auto-executed via a scriptnode when the scene opens.
    But I use pickle for storing out just about everything: pose data, animation data, preferences… just makes it super easy.

  7. Hi Eric. Thanks for the great tip, I only found this recently and it’s a great way to access data on nodes!

    I recently wrote a tool using this that allows animators to lock referenced attributes. I know you state that all the scripts on the website are Apache License v2.0. I’d like to release the entire project, including this script, as LGPL with attribution to you as the original author. Would that be okay? Normally, this wouldn’t be a big deal, but some of my friends who want my script released publicly work at studios with odd ideas about licenses.

  8. Permission granted, thanks for asking :)

  9. Wow, that was fast! Thanks Eric, I appreciate it.

Comment are closed.