Lesson 6.1Lesson 6.1 · Scripting Rhino & Grasshopper
Python in Grasshopper
The script component: a patch of real code sitting inside the visual graph, taking wires in and sending wires out
When the visual graph gets tangled, drop in a script component - a small window where you write Python that plugs straight into the wires.
Grasshopper is a visual programming language: you solve problems by dragging components and drawing wires between them. It is wonderful for many things and awful for a few - a loop that feeds itself, a fiddly bit of logic, a calculation that would take fifteen components and one line of code.
That is what the script component is for. It is a single component you drop on the canvas that contains real Python. Wires still flow in and out, so it lives happily beside every other component - but inside, you have the full language: variables, loops, conditionals, functions. This lesson is about that boundary: how data crosses from the graph into your code and back again.
Script component = code on the canvas. Inputs -> variables. Assign a -> output. Rhino 8 = CPython 3.
Why script inside a visual tool at all
Grasshopper solves problems by wiring components together, and for a huge range of parametric work that is faster and clearer than code. So why script at all? Because some things the visual graph does badly. Iterative logic - where each step depends on the last - is painful to wire but trivial to write as a for loop. Conditional branching - do this if a room is over 15 sqm, otherwise that - sprawls into a mess of Stream Filter and Dispatch components but reads as three lines of Python. And sometimes you simply know the code already and reaching for a component you half-remember is slower than typing what you mean.
The honest rule is: use components for the flow, drop to code for the knots. A mature Grasshopper definition is usually mostly components with a few script components at the awkward joints - not one giant script that ignores the canvas, and not a heroic all-visual contraption avoiding code on principle. You are not choosing sides; you are using the right tool for each stretch. This whole module lives at that boundary, and it starts with the mechanics of getting data in and out of a script component cleanly.
There is also a quieter reason to script inside Grasshopper: reuse and clarity. A component someone wired up two years ago is a puzzle to inherit - you have to trace every wire to understand it. A short, well-named script with a comment at the top often explains itself, and you can copy it between definitions without re-wiring anything. Once you are comfortable, a script component becomes a little reusable tool you carry from project to project: your own averaging component, your own labeller, your own bay-grid maker. That personal toolkit, built up over time, is one of the real dividends of learning to script rather than only to wire.
Be honest about the flip side, though: a script component is a black box on the canvas. Where a chain of components shows its working at every step - you can hover any wire and see the data - a script hides its logic inside, visible only if someone opens it. That is a fair trade for a knotty calculation, and a poor one for something a Dispatch and a Cull would show plainly. The skill is knowing which is which, and it is why this lesson keeps returning to the same rule: reach for code when it genuinely reads more clearly than the wires, not merely because you can.
Components for the flow; code for the knots. Most defs are a mix.
Which Python is this, exactly
Being precise here saves confusion later, because Grasshopper has had two Python engines. The older GHPython component runs IronPython 2.7 - an implementation of the now-ancient Python 2 built on .NET. It is still around in older files and still works, but Python 2 has been end-of-life for years and you should not start new work in it.
Since Rhino 8, Grasshopper ships a new Python 3 script component running real CPython 3 - the same Python you install from python.org. This matters enormously: it means you can pip install normal libraries like numpy or pandas and use them right inside Grasshopper, which the old IronPython engine could not do cleanly. Throughout this module, the script component means this modern CPython 3 one unless stated otherwise.
Either way, one thing is constant: your code runs with access to Rhino's geometry library. Inside the component you typically write:
import Rhino.Geometry as rg
pt = rg.Point3d(3.0, 5.0, 0.0)
vec = rg.Vector3d(0, 0, 10)Rhino.Geometry is part of RhinoCommon, Rhino's full geometry SDK, and it is what lets your script make points, curves and surfaces that the rest of the canvas understands. We meet it properly in lesson 6.3.
One practical consequence of the CPython 3 shift is worth flagging now, because it will save you a confusing hour later. Because the new component is real CPython, code you write and test in a normal editor - or that an AI assistant generates - runs the same way inside Grasshopper, which was never quite true of the old IronPython. Standard-library modules like math, random, csv and json all behave exactly as they do everywhere else in this course. The main things unique to the Grasshopper context are the Rhino.Geometry types and the input/output plumbing; the plain Python underneath is just Python. That continuity is the reason this course teaches the language first and the tools second - the fundamentals genuinely transfer.
Old = GHPython / IronPython 2.7. New (Rhino 8) = Python 3 / CPython. Use the new one.
Inputs become variables; the a=... pattern sends values out
Here is the core mechanic, and it is beautifully simple. Every input on the script component becomes a variable in your code, named after the param. The defaults are x and y; rename the param to radius and a variable radius appears. Every output is a name your code assigns to; the default output is a. Whatever you store in a gets pushed back onto the canvas through that wire.
So the smallest useful script is genuinely this:
# inputs on the component: x, y
# output on the component: a
a = x + yWire two number sliders into x and y, and a carries their sum out. Add a second output param named b, and you can return two things:
a = x + y
b = x * yThe values can be anything Python holds - numbers, strings, lists, or Rhino geometry. This is the whole contract between code and canvas: read the inputs as variables, do your work, assign the outputs by name. There is no return, no print to the wires - just assignment. Forgetting to assign an output is the single most common beginner slip: the code runs, but the output param stays empty because nothing was ever put in a.
A subtle but important point: the output can hold a whole collection, not just one value. If you assign a Python list to a, Grasshopper unpacks it into a list on the wire, so one script can emit many items:
a = [rg.Point3d(i, 0, 0) for i in range(10)] # ten points outThat list comprehension - straight from Module 2 - builds ten points and sends them all through the single output a. This is how a script becomes a generator of geometry rather than a calculator of one number, and it is the pattern behind every worked example later in this module. Assign a single value and you get one item on the wire; assign a list and you get many.
Input param name = variable in. Output param name = variable you assign. No return.
Item, list or tree: how much arrives at once
One setting changes everything about how your script behaves: the access mode of each input, set by right-clicking the param. There are three choices.
Item access (the default) hands your code one value at a time and runs the whole script once for each item. If you wire in a list of ten numbers with x set to Item access, your script executes ten times, with x being a single number each run. Simple, but you cannot see the other items - no totals, no sorting, no looking at neighbours.
List access hands your code the entire list in one run, as a real Python list. Now x might be [3, 5, 8] and you can do list things:
# x set to List access
a = sum(x) / len(x) # the averageTree access hands you the whole Grasshopper data tree - every branch - which we unpack in lesson 6.4. The guidance is to reach for the simplest mode the task allows: Item when each value is independent, List when you need to see a whole branch together, Tree only when the branch structure itself matters. Getting this choice right is often the difference between a script that works and one that quietly does the wrong thing to the wrong number of items.
There is a matching setting on the output side, called the output type or list access on the output, but the everyday rule is simpler than the inputs: if you assign a list, you get a list out. The one habit worth forming early is to decide the access mode deliberately for every input, rather than accepting the Item default and wondering why your averaging script keeps returning a list of unchanged numbers. When a script behaves strangely, the access modes are the first thing to check - more often than not, an input that should be List is still set to Item, so your code is being run once per value and never sees the collection it needs. We return to the fullest mode, Tree access, in lesson 6.4, once trees themselves make sense.
Python 3 script component
The modern CPython 3 scripting component in Rhino 8 Grasshopper
Runs real CPython 3, so you can pip install numpy or pandas. This is the one to use for new work.
GHPython (IronPython 2.7)
The legacy Python 2 script component
Still present for old files, but Python 2 is end-of-life. Do not start new scripts in it.
RhinoCommon / Rhino.Geometry
Rhino geometry SDK available inside the script
import Rhino.Geometry as rg gives you Point3d, Curve, Brep and more that the canvas understands.
Item / List / Tree access
Per-input setting for how much data arrives at once
Right-click an input to set it. Item runs the script per value; List gives a whole branch; Tree gives everything.
Workshop - a script component that averages and labels
Build the smallest useful script that actually needs code: take a list of numbers, return both their average and a short text label. It exercises List access, multiple outputs, and the assign-the-output rule in one go.
Rhino 8 (for the CPython 3 script component) with Grasshopper. No extra libraries required.
Goal: return the average of a list plus a text label, from one script component Inputs: one number slider set feeding a list into x Time: ~25 minutes
- 1In Rhino 8, open Grasshopper and drop a Python 3 script component on the canvas. Wire a list of numbers (a Number param with several values, or a Series component) into the input
x. - 2Right-click the
xinput and set its access to List - this is essential, or your script runs once per number and can never average them. - 3Add a second output param: right-click near the outputs, add one, and rename it
b. You now have outputsaandb. - 4In the code, compute
a = sum(x) / len(x)for the average, then build a label such asb = "avg of " + str(len(x)) + " values = " + str(round(a, 2)). Assign both - remember, nothing comes out of an output you never set. - 5Hover the outputs to confirm
ais one number andbis the text. Now change the input list and watch both update. Bonus: guard against an empty list with anif len(x) == 0:check so the script never divides by zero.
You’ll walk away with
A working Python 3 script component with List access on its input and two outputs - a numeric average and a formatted text label - that updates live as the input list changes.
Three altitudes on the same idea
Read the band that fits you — or all three.
A script component is the escape hatch for the logic your definition cannot wire cleanly. Adaptive facade rules, floor-by-floor massing that depends on the floor below, code-compliance checks that branch on room type - these are natural as a few lines of Python inside an otherwise visual definition. You keep the parametric responsiveness of Grasshopper and gain the expressiveness of a real language exactly where the graph would otherwise sprawl.
Even interiors work that lives in Rhino has knots worth scripting. Distributing furniture on a grid, labelling a set of panels, computing a running total of areas across a layout - each is cleaner as a short script feeding back into your Grasshopper layout than as a wall of components. You do not need to script everything; you need the one small window where typing the logic beats hunting for the component.
Grasshopper plus a little Python is one of the most employable combinations in the studio. Learning where the script component fits - and the input-becomes-variable, assign-the-output contract - puts you ahead of peers who only ever wire components. It is also the gentlest on-ramp from pure code into computational design, and it feeds directly into the Computational Design and Generative AI courses in this Academy.
“If I use a script component, I am admitting Grasshopper failed - real GH users solve everything with components.”
Do it yourself
Reason about the code-canvas boundary.
- 1On a script component, what determines the name of the variable you read an input from?
- 2How does a value leave a script component and get back onto the canvas - what do you do in the code?
- 3Your output param is empty even though the code ran without error. What is the most likely cause?
- 4You wire a list of 20 numbers into an input set to Item access. How many times does your script run, and what is the input each time?
- 5Which Python engine should you use for new work in Rhino 8, and why not the older one?
The one line to carry out
Peer-reviewed journals & authoritative standards
- 01Grasshopper 3D — Wikipedia, 2026.
- 02Rhinoceros 3D — Wikipedia, 2026.
- 03Rhino.Python guides — McNeel / Rhino Developer, 2026.
- 04Python (programming language) — Wikipedia, 2026.
We have been writing geometry with Rhino.Geometry inside a live Grasshopper session. But what about code that runs where Rhino is not open at all? Next we compare the tools that need Rhino running with the standalone library that reads and writes .3dm files anywhere.
The author
Amogh N P
Architect, interior designer, and creative polymath. Studio Matrx began in his notebooks — his vision of design made honest, useful, and open to everyone. Its Academy is written and taught in his memory, and free, forever.
More about Amogh →