If you’re like me, you like to always be using the latest version of an Autodesk product. The 2014 series has just been released and it is always quite a bit of work to convert you’re existing toolset up to the latest build.
In the case of Maya 2014, there are more than just a few issues, such as:
Python 2.6.3 -> Python 2.7.3
PyQt to PySide
PyMel 1.0.4 -> PyMel 1.0.5
Perforce module
Then there are always third-party compiled plug-ins to worry about. Any smart team will try to keep these to a minimum.
So the first big issue is the Python version upgrade. This should not be too big and on the surface it makes some sense to move up to the latest (last!) and greatest of the Python 2.x series. I’m pretty sure 2.7 will be the last of the supported 2.x series as everybody is supposed to move up to 3.x as soon as possible. My theory is that there will be some critical mass hit where most have updated to 3.x in their pipeline and then practically everybody else will migrate over in a very short period of time. I have not personally seen the roadmap for when this will happen to Maya (and probably non-coincidentally MotionBuilder 2014 which is using Python 2.7.3 now as well) but I suspect they’ll upgrade to a 3.x soon.
P4Python
The first heavily used third-party python module that I needed to upgrade was Perforce, which happened to be one of the most problematic. Unfortunately, the build of P4Python from the Perforce website does not import into Maya’s 2.7.3 python. According to this chart:
For detailed compatibility, please check the following table:
Python Release | P4Python Release
======================================
2.3 or earlier | not supported
2.4 | 2008.2 (unsupported)
2.5 | 2007.3 up to 2009.2 (unsupported)
2.6 | 2009.1 or later
2.7 | 2010.1 or later
3.0 | 2010.1 or later (unsupported)
3.1 | 2010.2 or later (unsupported)
3.2 | 2011.1
any of the latest versions (> 2010.1) of P4Python should work. However none of them do. I’ve tried all of them.
It seems that you must make a special custom build with “the version of Visual Studio that was used to build Maya” which is supposed to be VS2010. (Building P4Python and PyQt for Maya 2014). I had a hard time getting this to work, but with some help from one of my buddies I configured a simple build .bat file for you. You can get it here: perforce_build_x64_maya.bat or if you just want the results, go get the builds here: P4Python compiled for ADSK 2014 download (64-bit, of course) These should import fine into both Maya and MotionBuilder 2014 64-bit.
PySide
Autodesk now ships pre-compiled builds of PySide which is a replacement wrapper for the QT UI libraries that work so well and are so robust and beautiful in some of the latest Autodesk products. This is a huge relief as the licensing around the PyQt wrappers were tricky and some companies were reluctant to adopt and also you were supposed to build them yourself, though there was always a version floating around the interwebs you could find, if you looked hard enough. The coolest thing about PySide is that it is Open Source.
There are quite a lot of little tricks to getting Qt UIs embedded inside of Maya and get them talking together. For the most part, these have been thoroughly explored and there are solutions or workarounds for most common use cases inside of Maya. Nathan Horne is one of the pioneers in this area and has shared a ton of useful info: Nathan’s Mega-post and some others
After reading through that ton of info and if you’ve implemented Qt into Maya, you’ll know that the wrapinstance() function is a key component to getting it all going. Luckily Nathan wrote an equivalent for PySide: here
If you’re like me, you like loading Qt .ui files directly into Maya instead of compiling them into python via the pyuic.exe process. You’ll need to use the loadUiType() function to do this. This function needs to be modified slightly to accomodate PySide. Here ya go!: PySide loadUiType.py
import pysideuic import xml.etree.ElementTree as xml from cStringIO import StringIO #import QtGui def loadUiType(uiFile): """ Pyside lacks the "loadUiType" command, so we have to convert the ui file to py code in-memory first and then execute it in a special frame to retrieve the form_class. """ parsed = xml.parse(uiFile) widget_class = parsed.find('widget').get('class') form_class = parsed.find('class').text with open(uiFile, 'r') as f: o = StringIO() frame = {} pysideuic.compileUi(f, o, indent=0) pyc = compile(o.getvalue(), '', 'exec') exec pyc in frame #Fetch the base_class and form class based on their type in the xml from designer form_class = frame['Ui_%s'%form_class] # base_class = eval('QtGui.%s'%widget_class) base_class = eval('PySide.QtGui.%s'%widget_class) return form_class, base_class
You’ll notice QtGui replaced with PySide.QtGui.
I happen to use a lot of the decorator tricks for signal/slot connections and there are some marked differences in the way PyQt does these compared to PySide. Here’s two pages with some helpful examples:
Signals and Slots
Tutorial
Trickier examples
I also happen to find the Documentation for PySide very clear and easy to use. Here’s one of my favorite sites: PySide – Python for Qt
Here’s some other nice pages with PyQt to PySide conversion help: PySide and PyQt
and a supposed auto-converter?: PySider
PyMel
PyMel version has been iterated as well and with it comes some improvements, I’m sure. However, there are some minor issues introduced as well. The first couple I’ve found are related to the area of Virtual Class creation discussed here. It seems the factories.py module has a minor bug in it that you need to hack. I’ve submitted the bug request at the pymel google code repo where the project is maintained, but until that gets fixed, if you are using the pymel.all.factories.registerVirtualClass() method you need to hack ‘validSpecialAttrs’ variable in PyMel’s factories.py and add ‘__apicls__’ to the declaration.
To be continued, probably
Those are the major hurdles I’ve had to overcome so far in upgrading. If you have any questions or find any other obvious areas that need attention when you upgrade your toolset to Autodesk 2014, let me know and I’ll try to keep a running list here. Good luck.
Thanks for the share, I bet it’ll save my life soon 🙂
Hi,
thanks for the roundup, especially regarding PySide.
Is anyone using Eclipse with PyMel on 2014 sucessfully yet? I set it up exactly the same way as I did for 2013 – but this throws errors in eclipse autocompletion.
best
Felix
Yep. I’m getting completion no problem. Though it is always a bit finicky getting PyMEL completion in PyDev. I usually just start from scratch and create a new project with new interpreter, re-configure those python paths so site-packages is after the completion/py as per the installation instructions. A tricky gotcha is to make sure your workspace is not in the same directory as the project’s root, I think that has messed me up before.
That being said, pymel 1.0.5 in Maya2014 has some hiccups. I think te virtualClasses are broken by default. You have to hack factories.py and add ‘__apicls__’ to the validSpecialAttrs list/set (I’ve submitted this bug).
Good write up Jason.
I found another PyMel 1.0.5 bug today (albeit minor one). The command pymel.core.windows.savePrefs() command is not present in the current version.
If you are using this command, you can switch to…
import maya.cmds
maya.cmds.savePrefs
… for the time being.
There is a bug report already existing for this bug.
I fear the Python 3.0 switch 🙂
Thanks for the info, very handy to know. A problem I ran into when I tried the p4 python for Maya 2014 x64 you provided is it seems to have problems adding files to changelists using the p4.fetch_change (which worked in Maya 2013). Code sample and output below.
The file (below) I am trying to submit is checked out and in the default changelist.
from P4 import P4,P4Exception
p4 = P4()
p4.connect()
changeList = p4.fetch_change() #create new CL on the fly
changeList._description = "Crikey!"
myfile = ['//testing/art/src/wallaby/wallaby.ma']
changeList._files = myfile
p4.run_submit(changeList)
print changeList
p4.disconnect()
# Error: P4Exception: file s:\tools\python_tools\P4.py line 510: [P4#run] Errors during command execution( "p4 submit -i" )
[Error]: "Error in change specification.\nCan't include file(s) not already opened.\nOpen new files with p4 add, p4 edit, etc." #
The error looks more like a workflow issue, like you need to use p4 add first. Not in the compiled P4API.pyd
It’s already open for edit and sitting in the default changelist, if I try to add it again I get this back from Perforce:
["//depot/testing/art/src/wallaby/wallaby.ma - can't add (already opened for edit)", '//depot/testing/art/src/wallaby/wallaby.ma - warning: add of existing file']
Figured it out, was user error. A few weeks ago while experimenting in P4V I had changed an advanced workspace option in Connection>Edit Current Workspace>Advanced tab: “On submit: revert unchanged files” and didn’t realize it was a global tweak. After I was done I forgot to set it back to the default (“On submit: submit all selected files”). I thought the setting applied only to commands within P4V.
Anyways, since I was testing on an unchanged Maya scene, the file immediately reverted, p4 then couldn’t find anything in the default pending changelist and gave the error.
Thanks so much for your post Jason. I just ran into the P4Python error when trying to move over to 2014 and this is going to save me a ton of searching.
I’m noticing a weird bug with the 2014 version of P4Python when handling exceptions. In 2013 the code below worked but in 2014 the connection is closed after the
except P4Exception:
statement. So unfortunately p4.errors always just returns an empty list. The only way I’ve found to work around this is just setting the exception_level to 0 and logging errors.Anyone else experience this and know of a workaround?
from P4 import P4, P4Exception
p4 = P4()
try:
p4.connect()
print p4.connected()
print p4.run_sync()
except P4Exception:
print p4.connected()
for e in p4.errors:
print e
Thanks Jason!
Thanks Jason, this is great info!
Do you know where to get a version of PySide that works in MoBu 2013.
I was able to make the ShotGun PySide version work, but it seems incomplete, it doesn’t have the pysideuic module: https://github.com/shotgunsoftware/tk-motionbuilder/tree/master/resources/pyside112_py26_qt470_win64
Thanks!
Manu
Pyside ships with the 2014 releases of MoBu and Maya. Don’t know about builds for 2013. Might not be possible.
I found a python 2.6 version here, but I can’t make it work with MoBu: http://www.lfd.uci.edu/~gohlke/pythonlibs/#pyside
At this point the only one that works is the one for ShotGun. I’ll try to use the pysideuic package from the official version with the ShotGun version, maybe that will work…
We still have productions on older versions of MoBu here, and we are not ready to switch. The past 3 versions of MoBu have been very unstable and it is costing us too much to switch.
Manu
Hey Manu,
I’m having success just trying to load either PyQt or PySide like this:
try:
from PyQt4 import QtCore
except:
from PySide import QtCore
Jason, in order to get your LoadUi code to work I modified it so that that instead of this:
base_class = eval('PySide.QtGui.%s'%widget_class)
I do this:
base_class = getattr(QtGui, widget_class)
That way I can be sure that QtGui is actually loaded in the current namespace.
You might also be interested in this:
How to load a user interface dynamically with PySide.
I now have almost everything working in MoBu 2013. The only remaining issue is that the embedded PySide UI does not resize with the MoBu FBTool window resize.
I am still using the ShotGun version of PySide, along with the pysideuic package from the official version.
Manu
I made a boilerplate script for making PySide/PyQt UIs in Maya (and Nuke as well as standalone) using either PySide or PyQt. Check it out: https://github.com/fredrikaverpil/pyVFX-boilerplate
Thanks very much for uploading the compiled P4API.pyd, seems it was exactly what I needed.
Hai Jason, can You write guidline to build PyQt for maya 2014 x64 for community?
it will be a great resource for us.
i follow step from this tutorial:
http://around-the-corner.typepad.com/adn/2013/04/building-sip-and-pyqt-for-maya-2014.html
but not clear at all and didn’t work for me.
please teach us to achieve what You get to work, thanks a lot 😀
Eric, you can contact me at jason[at]continuityai[dot]com for custom contract work.
Hi Jason. Thanks for the great blog. Using your loadUiType replacement method worked a treat with dynamically loading .ui files from Designer that was included with older Mayas. With the latest Designer 4.8.5 included with Maya, the XML created seems slightly different and the uiparser.py PySide module included with Maya fails on the line “bg_name = bg_i18n.string”. Looking at solutions including PyQt the common solution seems to be a try except clause:
try:
# We are compiling the .ui file.
bg_name = bg_i18n.string
except AttributeError:
# We are loading the .ui file.
bg_name = bg_i18n
Do you know of a way to Monkey patch this in Maya rather than physically edit the uiparser.py file on every users PC? I’ve tried, but to no avail so far.