Python 3 in Rhino
Rhino 8 and newer, embed two Python runtimes side by side:
- Python 3 is CPython, and reaches .NET and RhinoCommon through Python.NET
- Python 2 is IronPython, which runs on .NET itself
Python 3 is an addition, not a replacement. Your Python 2 scripts keep running on IronPython, and both runtimes are available in Rhino and in Grasshopper.
Scripts of either runtime are written in a refreshed Script Editor, and it is the editor that puts the rest of this page within reach: installing packages, and a real debugger with breakpoints, variables, and a call stack. That debugger also works inside Grasshopper components, which the old editor could not do.
What You Get With Python 3
Python 3 opens up the wider Python world:
- Packages from PyPI such as
numpy, declared in the script itself with#r: numpy - Separate package environments, for packages that clash with each other
- Current Python language features, and the libraries that expect them
#r: numpy
import numpy as np
import rhinoscriptsyntax as rs
points = np.random.rand(10, 3) * 100
for point in points:
rs.AddPoint(*point)
What Python 2 Still Does Better
IronPython runs on .NET with nothing in between, which shows in two places:
- Pure RhinoCommon calls are faster
- Real .NET multithreading is available
So the choice is per script rather than once and for all. Scripts that lean on packages want Python 3. Scripts that hammer RhinoCommon, or that need threads, can be better off staying on Python 2.
The Script Editor
Scripts of both runtimes are written in the Script Editor, opened with the ScriptEditor command. The same command runs scripts from macros, toolbar buttons, and aliases:
_-ScriptEditor _R "C:\path\to\script.py"
See ScriptEditor Command in Macros for the other command options, and Scripting: Python for writing and debugging scripts.
EditPythonScript command and its editor still exist, but are deprecated. New work belongs in ScriptEditor.Python 3 in Grasshopper
Grasshopper has a Python 3 script component alongside the older GHPython component. ghpythonlib works the same under Python 3 as it does under Python 2:
import ghpythonlib.components as ghcomp
a = ghcomp.Circle(x, y)
Grasshopper 2 ships its own Python 3 and Python 2 script components. ghpythonlib is a Grasshopper 1 library and is not available there.
Details are in the component guides:
Publishing Scripts as Plugins
Scripts do not have to stay scripts. The Script Editor can gather them into a project and build that project into a Rhino or Grasshopper plugin, so your scripts become Rhino commands and Grasshopper components that others install like any other plugin.
- Creating Rhino/Grasshopper Script Plugins for making a project, and adding commands and components to it
- Publishing Rhino/Grasshopper Script Plugins for building and sharing the plugin
Moving a Script to Python 3
Most of the work is ordinary Python 2 to Python 3 work: print is a function, / on two integers no longer truncates, range replaces xrange, and str replaces basestring. The Python documentation covers the language changes.
Three changes catch Rhino scripts in particular.
Enum members named None. None is a keyword in Python, so Python.NET exposes such members in upper case:
# python 2
value = Rhino.Geometry.Mesh.MeshType.None
# python 3
value = Rhino.Geometry.Mesh.MeshType.NONE
Methods returning collections. A .NET method returning an IEnumerable gives you an iterator in Python 3, not a list. Wrap it when you need indexing or a length:
items = list(some_method())
Subclassing .NET types. Python.NET expects the base constructor to be called, so a class deriving from a .NET type needs a super() call in its __init__. IronPython let you leave it out:
import Rhino
class MyConduit(Rhino.Display.DisplayConduit):
def __init__(self):
# required in python 3
super().__init__()
self.points = []
Without it, the object is not fully constructed and calls into it fail.
