Since the introduction of Python 3 in 2008, Python 2 and 3 have been supported side-by-side by the Python Software Foundation (PSF) and the broader Python Community.

This stopped on January 1st, 2020 when Python 2 support from the PSF officially ended.

 

Why did we need to change the Python version?

Dynamo, and many other C#-based environments, used a tool called IronPython to move data between .NET objects and Python scripts. Unfortunately, IronPython had not yet been updated to Python 3 at the time of this change (note that IronPython has only recently released a version compatible with Python 3). Dynamo had therefore transitioned to use the standard native Python interpreter (aka CPython) instead that uses Python 3.

In addition, this means it is now possible for Dynamo graphs to benefit from Python libraries that include native extensions that were not accessible in IronPython, such as NumPy, SciPy, and Pandas.

The move to Python 3 now allows Dynamo users to access popular modern libraries and continue to access new platform features, essential maintenance, and security patches.

 

Backward Compatibility

Dynamo 2.7 introduced the new Python engine, CPython3, that provides access to Python 3 inside of Dynamo. However, there is no guarantee that any code written in the CPython3 environment will work in previous versions of Dynamo. Code authors should ensure backward compatibility with both the IronPython2 and CPython3 versions as desired.

 

What does this mean for you and your Python-containing graphs?

If you are not the author of the particular graph you are using (or the Python nodes it contains), please contact the author and let them know about these changes so they can make the appropriate updates where necessary.

If you are the author of the graph, please continue to read the guidance below to understand how these changes may affect your Python nodes and how to make any changes.

Python 3 is fundamentally the same language as Python 2, but there have been changes to syntax and the core library to make Python more consistent and learnable and to have improved Unicode support.

Some Python 2 programs will run as normal on Python 3, but a lot of common constructs will require small changes, including the print statement. Luckily, many of these can be automated.

 

How to make changes to your Python nodes for Python 3

Typically, Python scripts can run using either the IronPython2 or CPython3 engines. For any cases where your script contains syntax that has changed between versions, we have made it easier for you to update your script by including an automatic code converter in the Python node called the Migration Assistant.

Using the migration assistant, all you need to do is click on the 2->3 icon and Dynamo will let you know which changes are needed and will give you the option to decline or accept the conversion.

As the “Python Script From String” node simply executes the Python code passed into it, rather than providing a text editor environment, it does not have access to the Migration Assistant. If you wish to use this feature you will need to copy and paste your code into a Python node temporarily before copying and pasting it back into your code block or string input node.

If you are curious about diving deeper into the differences between the two Python versions, here are two external links to get you started:

 

UI Warnings and Documentation

If you now open a graph containing old Python nodes using the IronPython2 engine, you will see a UI dialog reminding you of the transition to the CPython3 engine and that eventually, Dynamo will move completely to Python 3.

 

This dialog prompt has a More Information link that when clicked displays more information about the Python 2 to Python 3 update in the Dynamo documentation browser. This information can also be displayed by clicking on the “?” button at the bottom of the python script editor window as shown:

 

You can also bring up this information in the documentation browser by selecting the “Learn more about Python” menu option when you right-click on the python node.

 

Key syntax changes in Python 3

Below, you can find a list that includes some of the key syntax changes between Python 2 and Python 3. Please note that this is by no means an exhaustive list but instead a selection of some of the most widely used features that have been affected.

Print Function

The print syntax is probably the most widely-known change. Even though it is not often used in Dynamo, here is an example showing how the print statement has changed.

Python 2 Python 3
print 'Hello, Dynamo!'

// Hello, Dynamo!

print('Hello, Dynamo!')

// Hello, Dynamo!

 

Integer division

This change will not raise any exceptions in your script, but it might affect the output. When presented with integer operands, the default division operator behavior in Python 2.x is to use classic division which truncates the decimal place and returns an integer. When given a pair of floating-point operands, it returns the actual floating-point quotient (aka true division). Python 3 performs a true division even with integers.

Python 2 Python 3
1/2

// 0

1/2

// 0.5

1.0/2.0

// 0.5

1.0/2.0

// 0.5

 

xrange

xrange is usually used in combination with a for-loop or list-comprehensive statements. When you only need to iterate once, it is generally faster to iterate over xrange() compared with range(). In Python 3, the range() was implemented in the same way as the xrange() function, so that a dedicated xrange() function no longer exists. Instead, xrange() raises a NameError.

Python 2 Python 3
n = 1000000

for i in xrange(n):

  print i

// 1,2,3,4,5…

n = 1000000

for i in range(n):

  print(i)

// 1,2,3,4,5…

 

Raising and handling exceptions

Where Python 2 accepts both notations – the ‘old’ and the ‘new’ syntax – Python 3 raises a SyntaxError if we don’t enclose the exception argument in parentheses. The handling of exceptions has also slightly changed in Python 3, where we now need to include the “as” keyword.

Python 2 Python 3
raise IOError, "file error"

// IOError: file error

raise IOError("file error")

// OSError: file error

try:

  let_us_cause_a_NameError

except NameError, err:

  print err, '--> our error message'

// IOError: file error

try:

 let_us_cause_a_NameError

except NameError as err:

  print(err, '--> our error message')

// OSError: file error

 

IronPython2 and CPython3 Compatibility

A detailed list of compatibility differences between the two engines can be found on this wiki. These issues are related to differences in behavior between the IronPython2 and CPython3 engines that cannot be addressed by mere syntax changes or by using the migration assistant. As of Dynamo 2.11, the Dynamo team has addressed many of these issues by aligning features between the two engines while the rest are not planned currently.

 

Feedback

The team is always looking for feedback from our users to continually improve Dynamo and this case is no different. Please provide any feedback you have specific to Python nodes on this forum thread. Happy scripting!