Mati Codes
# _  _ ____ ___ _    ____ ____ ___  ____ ____ #
# |\/| |__|  |  |    |    |  | |  \ |___ [__  #
# |  | |  |  |  |    |___ |__| |__/ |___ ___] #
#                                             #
# _  _ ____ ___ _    ____ ____ ___  ____ ____ #
# |\/| |__|  |  |    |    |  | |  \ |___ [__  #
# |  | |  |  |  |    |___ |__| |__/ |___ ___] #
#                                             #

March 27, 2021

HOW TO CONVERT MAYA PYTHON 2 CODE TO PYTHON 3


Python 3 is finally here in Maya 2022! If you haven't converted your scripts to Python 3, I'll go over how you can automatically convert your Python 2 scripts and modules to Python 3.

There are A LOT of changes between Python 2 and Python 3 and Python 3 code is not designed to be backwards-compatible with Python 2. You may only be using a subset of affected libraries and features in your Maya scripts, but you're probably still going to want to avoid making the updates manually.

Python 3 includes a script called, 2to3.py, which handles automatically converting your code for a lot of the changes that occurred between Python 2 and Python 3. Take a look at the 2to3.py documentation which lists the fixes that it applies to get an idea of how big of a difference there is between Python 2 and Python 3.

My goal with this blog post is to help you convert your code as fast a possible with the least amount of fuss while also showing you some options for maintaining backwards-compatibility with Python 2. You can achieve cleaner results with manual conversion, but I know that may not always be desired or practical. You can always go back and clean up your code as time allows and especially as you drop support for Python 2. I really recommend reading this blog post in its entirety before getting started to understand what changes are being made and there are a few scenarios that you'll want to consider.

Should I use 2to3, futurize, or modernize?

As mentioned, Python 3 comes with a library called lib2to3 which as the name suggests converts Python 2 code to Python 3. 2to3 focuses on porting your code to Python 3, but it does not attempt to make it backwards-compatible.

On the other hand, Maya 2022 also comes with the python-future library installed which uses 2to3 under the hood, but it can convert your code and make it backwards compatible with Python 2 with the futurize script. This sounds wonderful, but the catch is that to use it as intended your end-user needs to have the future python package installed in their older Maya installations or you need to provide the future package with your code.

Lastly, the python-modernize library will also give you backwards-compatibility and only relies on the built-in six library as the compatibility layer, but you'll need to install python-modernize to get access to the conversion script.

I'm going to show you how to use the conversion scripts for these three methods and cover more in-depth the pros and cons for each. Note that none of these libraries is a complete solution, but if you're lucky, they'll get the job done or get you most of the way there.

Backup

Make sure you have a backup of the code you'll be converting. The way I'm showing you how to use the conversion scripts will also create a backup in the process, but just the be on the safe side, it's not bad to keep another copy.

2to3

Summary

We're looking at 2to3 first since it's at the core of futurize and modernize and the other tools adopt a similar script interface to run the conversion. As I mentioned, 2to3 does not attempt to keep any backwards-compatibility so there's no additional compatibility layer like the other conversion tools. It just outputs pure Python 3. I mention this approach only because some people may be fortunate enough to move to Maya 2022/Python 3 and never look back or may prefer to maintain a copy of legacy Python 2 code and a separate branch with clean Python 3 code. Here's what the conversion command looks like:

# For a single file or list of files
"C:\Program Files\Autodesk\Maya2022\bin\mayapy.exe" -m lib2to3 --nofix=long -w my_script.py
# To convert all files recursively in a folder
"C:\Program Files\Autodesk\Maya2022\bin\mayapy.exe" -m lib2to3 --nofix=long -w my_directory/

This will edit your ".py" files to apply the fixes, but it will backup the files first as ".py.bak". It won't touch or backup ".py" files that it finds don't need any fixes. I also added to skip the "long" function because that interferes with maya.cmds like maya.cmds.ls(long=True). I find that I use the ls command in that way a lot more than using the long data type.

2to3 also outputs to the terminal the changes that it's making. Lines with "minus" at the beginning is what you had before and lines with "plus" is what it changed the code to. This is a good way to start learning to write Python 3 compatible code. You can run without the "-w" flag to just inspect what changes it would make without writing out anything.

futurize

Summary

Maya 2022 comes with the python-future library installed and is available in both Python 2 and Python 3 modes. Autodesk is likely using this and encouraging it. The python-future library comes with a script called, futurize-script.py, that we'll be using to apply the conversion, but it also comes with a collection of modules that serve as a compatibility layer between Python 2 and Python 3. Let's look at the conversion command and then talk more about cross-compatibility. Here's what the conversion command looks like:

# For a single file or list of files
"C:\Program Files\Autodesk\Maya2022\bin\mayapy.exe" "C:\Program Files\Autodesk\Maya2022\Python37\Scripts\futurize-script.py" --nofix=lib2to3.fixes.fix_long -w my_script.py
# To convert all files recursively in a folder
"C:\Program Files\Autodesk\Maya2022\bin\mayapy.exe" "C:\Program Files\Autodesk\Maya2022\Python37\Scripts\futurize-script.py" --nofix=lib2to3.fixes.fix_long -w my_dir/

After running a conversion, you may notice new imports at the top of your code like this:

from __future__ import division
from __future__ import print_function
from future import standard_library
standard_library.install_aliases()
from builtins import zip
from builtins import range
from past.utils import old_div
from builtins import object

__future__ is built-in to Python and no problem, but future, builtins, and past all belong to the future library and serve as that compatibility layer that I mentioned. Instead of using affected Python features directly (e.g. zip, range, division, etc.), you use functions with the same name from the compatibility layer and they'll do the right thing so you get the same result whether you're running Python 2 or 3. This backwards compatibility comes at a price because now your code depends on the future library when it runs. This is fine if your code is only going to run in Maya 2022, but a problem if you want it to work with older versions of Maya.

What can I do for older versions of Maya?

For older versions of Maya, you just need to install the future library for them as well. Once that library is available, your code will work just like in Maya 2022 running with Python 2. You can install the library using "pip" like this:

"C:\Program Files\Autodesk\Maya2020\bin\mayapy.exe" -m pip install future

This will work fine for your own installations of Maya or if you can do it for everyone on your team in a studio environment. If you maintain an open source Python library or share your code publicly, then this can be a problem. You can't really go and install the future library for people using older versions of Maya nor can you expect them to do it on their own. You could include the future library WITH your code, but perhaps modernize is a better option for you.

modernize

Summary

The python-modernize library tries to achieve cross-compatibility like python-future, but it doesn't depend on an external compatibility layer. Instead, it uses the six module as its compatibility layer which comes built-in with the latest versions of Python 2 and with Python 3. You just need to install modernize to get access to the conversion script. You could install modernize into any Python interpreter. It doesn't need to be installed in Maya's Python interpreter, but if that's all you've got, here's how to do it:

"C:\Program Files\Autodesk\Maya2022\bin\mayapy.exe" -m pip install modernize

Once you have modernize installed, you use it just like the other conversion scripts:

# For a single file or list of files
"C:\Program Files\Autodesk\Maya2022\bin\mayapy.exe" -m modernize -x fissix.fixes.fix_long -w my_script.py
# To convert all files recursively in a folder
"C:\Program Files\Autodesk\Maya2022\bin\mayapy.exe" -m modernize -x fissix.fixes.fix_long -w my_dir/

modernize will apply fixes just like the other tools, but mostly you'll just notice that the compatibility imports will be different.

from six.moves import range
from six.moves import zip

Final Thoughts

Whichever route you take, try running the conversion and testing your code. As I mentioned, none of these will fix everything, but they will reduce the amount of time and energy you'll need to devote to it. Test your code and fix the remaining issues manually.

Start writing modernized Python 2 and eventually Python 3 code. This is something that you'll need to keep working on with new code you write. Test new code in Python 3 first to get in the habit of writing modern Python 2.

Hope this helps you get started migrating over to Python 3. Let me know if you run into any issues when converting or find any particularly tricky code that doesn't auto-convert.

>>>

Tags

python, maya, python 3 adoption, maya 2022, 2to3