Rhino WIP Feature: Python 3.13

Next build of Rhino WIP is going to deploy Python 3.13.3

Why?

Python 3.9 currently shipping with Rhino 8, is going to hit End-of-Life towards the end of 2025.
One of the major wins for having Python 3 in a dotnet app is access to packages that use python C API. if these packages drop support for Python 3.9, then that stops us from getting the more recent package versions inside of Rhino.

Which Python?

Python 3.13. This python is the current stable version and will only be getting security patches by the time Rhino 9 is likely released. It is currently the most recent version supported by Python.NET. VFX platform also suggest updating to Python 3.13 for the 2026 release cycle.

How do I use it?

Just install Rhino WIP and open ScriptEditor like before. It will deploy then new python runtime under ~/.rhinocode/py313-rh9 folder. We have also updated pythonnet to v3.0.5 since it is the latest version and has recently added support for Python 3.13

We have also improved error reporting when language initialization fails. Clicking on the error now opens the logs window with information on how to report the bug:

How does it affect my scripts or published plugins?

There should not be any changes needed to be done to your scripts. Any script with #! python 3 directive or .py3 file extension will automatically choose the new runtime. This includes Grasshopper python 3 scripts as well as any other scripts you run using Rhino command prompt.

:warning:
The only exception is packages that use Python 3 C API (are compiled against python39.dll) and do not have any Python 3.13 builds yet. They might fail install under the new runtime. This is a rare case. Most packages should install with no issues.

Is Rhino 9 going to support legacy Python 3.9?

No. Each Rhino version is fixed to a single Python 3 runtime version. This is what almost any other application that supports Python scripting does as well. We might consider adding an optional Experimental package to support newer or older python versions if there is a solid reason for it.

Is Rhino 9 going to ship with Python 3.13.3?

No. We will keep updating the runtime to newer patches e.g. 3.13.10 during the Rhino WIP life time, but Rhino 9 should remain fixed to Python 3.13.x


Obviously there is a lot that has changed in both of these projects so keep an eye on weird behaviour and crashes and please let me know. Internally our regression tests pass and I can run a script training a model on torch on both platforms.

I would love to hear your thoughts. You can tag me as @eirannejad on any of the comments that are specifically for me.

:rhinoceros::heart::snake:

14 Likes

Will Rhino 9 update to Python 3.14+ in future releases? What is the current version update policy?
@eirannejad

Yay!

2 Likes

Hi Niko -

No:

-wim

Thank you for your explanation! :slightly_smiling_face:

1 Like

@Niko Our bottleneck is the Pythonnet library that we use to connect to the python runtime and the maximum python version that it supports as of now is 3.13

@eirannejad following your logic I’m curious whether Rhino 9 drops IronPython support? That would be a major win for python devs.

I’m confused, why would dropping support for anything be considered a win?

It’s bad for users, no question.

But if you guys want to make breaking changes to hundreds of existing plug-ins (and the entire Grasshopper ecosystem) myself and others are more than happy to help anyone with a budget fix them.

Hi @stevebaer

This goes back to the zen of python → “There should be one-- and preferably only one --obvious way to do it”.

With Rhino v8 python devs face the ambivalence of supporting IronPython (a .Net implementation of the python language vs the CPython version of the language) and/or CPython code. These are basically different languages, with python3 supporting typehints. IIRC the compas project tried to maintain compatibility with both interpreters which led to loss of hair. ( see the post by @casas )
Dropping IronPython support doesn’t seem a controversial idea, since IronPython3 is basically sunset, supporting python 3.4 compatibility. It would be awkward to move towards python 3.13 and 3.4 simultaneously.

While supporting both interpreters in v8 provided a way of transition from py2 → py3, the ambivalence negated the progress made with v8 supporting py3.

A more complete set of arguments why less is more:

  1. Python 2.7 semantics ≠ Python 3 semantics

    • str/unicode vs bytes split, integer division, exception syntax, iterator vs list-returning APIs, print statement vs function, metaclass syntax, _cmp_, long vs int, ordering guarantees—the same code behaves differently. Every boundary between 2.7 and 3.13 becomes a minefield.
  2. IronPython 2.7 is ecosystem-isolated

    • It cannot use most C-extension wheels (NumPy, SciPy, lxml, cryptography, many ML libs). You’ll end up maintaining parallel plugin sets or writing shims—forever.
  3. Packaging schism

    • CPython 3.13 uses modern packaging (wheels, manylinux/musllinux, pyproject.toml). IronPython 2.7 is stuck with a shrinking set of source-only packages. Reproducible builds are far harder with two incompatible dependency graphs.
  4. Security & CVE surface area doubles

    • Two interpreters, two stdlibs, two ssl stacks, two zipimport/pickle attack surfaces. You inherit the highest risk of both. Patch cadence and CVE response must track both communities.
  5. ABI & embedding complexity

    • CPython 3.13 embedding APIs changed significantly in recent versions (init/finalize, stable ABI choices). IronPython embeds via .NET; CPython via native C API and pythonnet/hosting glue. Coordinating lifetime, GIL, finalizers, and unload in one process is brittle.
  6. Threading & GIL headaches

    • CPython has a GIL; IronPython 2.7 does not (but depends on .NET threading semantics). Mixing them invites deadlocks, starvation, and nasty reentrancy bugs when .NET calls back into Python while CPython holds the GIL.
  7. Diagnostics and tooling bifurcation

    • Different debuggers, profilers, tracers, symbol pipelines.

    • IronPython isn’t supported by modern IDE’s.

  8. Interop impedance mismatch

    • IronPython exposes .NET types natively; CPython needs pythonnet or custom marshaling. You’ll duplicate glue code or leak .NET types across boundaries—where 2.7 vs 3.13 string/bytes rules break in surprising ways.
  9. State management & isolation

    • Two module caches, two importers, two site-packages. Cross-talk via environment variables (PYTHONPATH, PYTHONHOME) and temp dirs causes spooky action at a distance.
  10. Memory footprint & cold-start hit

    • Two VMs, two garbage collectors (.NET + CPython’s refcount/GC), duplicated stdlib bytecode caches.
  11. Test matrix explosion

    • Every feature must be validated under: IronPy-only, CPy-only, and combined-loaded modes; single/multi-thread; debug/release; with/without native wheels. This will lead to flakiness.
  12. Long-term maintainability

    • New hires won’t know IronPython 2.7
  13. Compliance & audit burden

    • Auditors will ask why 2.7—an end-of-life language—exists in a 2025 product.
  14. Performance unpredictability

    • JIT (.NET) + native CPython create non-deterministic latency spikes (GC pauses on either side, GIL contention, pinning). Hard to model and harder to troubleshoot in prod.
  15. User & plugin confusion

    • Which interpreter runs which plugin? Why does a package install “fine” but fails at import under IronPython? Support tickets multiply.
1 Like

@jelle_feringa Good points. Thanks for listing them out here.

IronPython v2 will stay in Rhino 9 alongside Python 3.13. Not sure when we will be able to yank it out but I suspect we can have a conversation about it once Python 3 toolchain is mature enough to keep up with IronPython’s performance or replaced with other implementations that provide such performance benefits.

1 Like

The Grasshopper API via the PythonNet bridge is a long long way off what the IronPython one can do.

It would be incredibly damaging to the ecosystem, to yank IronPython even then. I know there’s C# and VB, but they have their own challenges. So it would be incredibly shortsighted, to not have native .Net Python support, even if the alternative (CPython via PythonNet) was stable or feature complete.

That’s on behalf of my users anyway. Personally if you guys want to make unnecessary, huge breaking changes, lots of us make our living fixing this sort of thing so…

1 Like

We’re not pulling IronPython support out of Rhino 9

4 Likes

Hi James, great to see you again :waving_hand: ! Just to clarify, if IronPython is removed now, all the Grasshopper plugins I’ve developed will stop working. I’m currently working on porting the code from IronPython to CPython. We might remove IronPython in the future, but I’m confident that by then, the migration to CPython will be complete.