You are on page 1of 15

Python Scripting in Grasshopper

a nifty guide

Stephen P. Maher / COL55


Email: smaher@nbbj.com
Slack: @smaher
Twitter: @StepMaher
Python Scripting in Grasshopper
a nifty guide
The Zen of Python
by Tim Peters

Beautiful is better than ugly.


Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases arent special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one and preferably only one obvious way to do it.
Although that way may not be obvious at first unless youre Dutch.
Now is better than never.
Although never is often better than right now.
If the implementation is hard to explain, its a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea lets do more of those!
Python Scripting in Grasshopper
a nifty guide

Those are the guiding principles of Python.

A sense of humor is required for their proper interpretation.

If youre using a programming language named after a sketch comedy troupe, you better
have a sense of humor.
Python Scripting in Grasshopper
a nifty guide
BACKGROUND
Rhino and Grasshopper use IronPython, not the general purpose parent language.

IronPython is an open-source implementation of the Python programming language which


is tightly integrated with the .NET Framework. IronPython can use the .NET Framework and
Python libraries, and other .NET languages can use Python code just as easily.
ironpython.net

SYNTAX
Variables inside the scripting editor should be lower_case with multiple words strung
together with underscores.*

single_string = "Hello, world!"


string_list = ["Hello", ",", "world", "!"]

For GHPython Input and Output variables, the first letter should be capitalized.
You cannot define a variable that starts with a number.
*Note: You may use camelCase, but know its not considered Pythonic. It really
should only be used to conform to preexisting conditions.

Comment Your Code! (remember to be Zen: readability counts)


# This is a comment, so it is ignored by the compiler.
Note the capitalization and spacing conventions.

"""
This is a multi-line comment.
Its useful for long comments or
temporarily suspending bits of code.
"""

#This is another multi-line comment.


#If you highlight multiple lines
#then hit "Ctrl + /", this is what happens.
Python Scripting in Grasshopper
a nifty guide
FUNCTIONS
Example short function.
# Define a function.
def short_function_name(var_one): Note the parentheses and the colon. You
need both, though you dont necessarily need
return(var_one) parameters.

# Call a function.
short_function_name(var_one)

Example long function.


# Define a function.
def long_function_name(
Note the indentation rules. One should avoid
var_one, var_two, var_three, lines of code greater than 80 characters.
var_four):
return(var_one)

# Call a function.
long_function_name(var_one, var_two, var_three, var_four)

Note the indentation and syntax conventions.

Example Script:
Iterative Fibonacci Sequence
def fib(n):
a, b = 0, 1
for i in range(n):
a, b = b, a + b
return a

for N in range(0, 15):


print fib(N)
Python Scripting in Grasshopper
a nifty guide
OBJECT METHODS
Most of the time you wont be defining functions, but calling them. These will often be
built-in functions belonging to objects called methods.

# Some input brep declared as "my_brep" in Grasshopper.


my_flipped_brep = my_brep.Flip()

# Declare to component output.


a = my_flipped_brep

Note that not all functions require parameters.

# Some input brep declared as my_brep in Grasshopper.


my_capped_brep = my_brep.CapPlanarHoles(tolerance)

# Declare to component output.


a = my_capped_brep

These are object methods. If you declare an


input Type Hint, the Python Editor knows
which methods to call for that object.
More on this in the following pages.
Python Scripting in Grasshopper
a nifty guide
ANATOMY OF THE GHPYTHON SCRIPTING COMPONENT_PART 01

Optional code input allows for referencing


external PY files or a [Panel] component. This
does not appear by default (right click).

The default names of the input variables. If it


goes into x, then you call x inside the script.

Optional out parameter shows any errors or


any output from a print method call.

The default names of the output variables. If


Use the ZUI +/-
you declare a = "Thing" then "Thing"
to add/remove
will come out into GH.
inputs and
outputs.
Default type

System Value Types

Rhino Value Types

When you right-


click, you get
this menu. Pay
attention to the
data structure of Rhino Reference Types
your inputs.

Text Display

Icon Display
Python Scripting in Grasshopper
a nifty guide
ANATOMY OF THE GHPYTHON SCRIPTING COMPONENT_PART 02

When you double click in the center of the component, the editor pops out. (It is not as
complex as the C# editor, for better or worse.)

Actually helpful in the beginning.


Links to GH forum, Rhino.Python forum and rhinoscriptsyntax
library help.

This is generally how I set up my scripts, especially if I plan to save


it as a GHUSER component or its contained within a cluster.

Note 01: There is no pre-determined bits of code or default


imported libraries like in C#. This Python editor is a blank slate, so
to speak.

Note 02: You do not need to declare variables. Python does this for
you when you assign them a value. You can, however, cast certain
values (like floats to strings and vice versa).

1. Define description, inputs, outputs.


2. Name (and NickName) the component.
3. Import relevant libraries and methods.
4. Declare variables.
5. Code body (action).
6. Declare outputs (push to GH).

Debugger (kind of, not really hopefully in the future). Displays


errors, any output from a print method call, and help when using
methods.
Not always the most useful resource, but can be a quick way of
understanding whats happening in your code.
If you want a true Debugger, use the Editor in Rhino by calling
it via _EditPythonScript or using a text editor (I have a few
Click Test to execute Click OK or Close to workarounds for using RhinoCommon in external editors, if youre
the code without close and execute. OK interested).
closing the editor. will save your script.
This saves your script Close will prompt you
automatically. to save with a dialogue
box.

This what the editor looks like when active.


Python Scripting in Grasshopper
a nifty guide
ANATOMY OF THE GHPYTHON SCRIPTING COMPONENT_PART 03

When you type a period after a library module name or alias:

This is the RhinoCommon Geometry library. Within it are all


the series of methods available. If you want to draw a line,
for instance, you will need to type
Rhino.Geometry.Line(point_01, point_02)
where the variables are pre-defined with Point3d values.

When you type an open parenthesis after a method name:

Description of method.

Return type (Parameters and their types)


Python Scripting in Grasshopper
a nifty guide
CONTROL STRUCTURES

Loops
for x in range(lower_int_bounds, upper_int_bounds, step_size):
# Do something.

Conditionals
# Import libraries.
if some_condition == True:
# Do something.
elif some_other_condition == True:
# Do something else.
else:
# Do the other thing.

Example Script
# Import libraries.
import math
import rhinoscriptsyntax as rs
import Rhino

# Define variables and lists.


var_01 = Var_01
var_02 = Var_02
step = Step
Pts = []

# Draw a sine wave using points.


for x in rs.frange(var_01, var_02, step):
y = N * math.sin(x)
pt = Rhino.Geometry.Point3d(x, y, 0)
Pts.append(pt)
Python Scripting in Grasshopper
a nifty guide
PYTHON CODING RESOURCES

The Python script engine is entirely based on RhinoCommon, the geometry library
inside Rhino/Grasshopper.

So I encourage you to learn about the methods available in RhinoCommon at the


SDK Documentation website here, and looking at the examples found here: Using
RhinoCommon from Python.

You should also learn about the methods in the rhinoscriptsyntax module here, and
looking at the examples found here: Rhino.Python rhinoscriptsyntax Module.

Python website

IronPython website

Rhino Scripting forum

Grasshopper Scripting forum


Python Scripting in Grasshopper
a nifty guide
USEFUL KEYWORDS, METHODS, AND HIDDEN SECRETS

print str(some_variable)
Write the contents of the string to the out output.

rh_doc = Rhino.RhinoDoc.ActiveDoc
Get access to the currently active Rhino Document.

gh_doc = ghenv.Component.OnPingDocument()
Get access to the currently active Grasshopper Document.
Note: Naming this ghdoc is a no-no. That variable contains a reference to the current
Grasshopper document solution. Id use it sparingly.

gh_canvas = Grasshopper.Instances.ActiveCanvas
Get access to the currently active Grasshopper canvas.

The scriptcontext module.


GHPython defaults to the active Grasshopper document, so if you want to target the
active Rhino document, you will need to point to it using the below method

import scriptcontext as sc
sc.doc = Rhino.RhinoDoc.ActiveDoc

The ghpythonlib library.*


*See next page.

try:
except:
Handle errors without killing the current execution. Example below.

try:
print my_pt_list[5].ToString() # This could fail if the my_pt_list
array has fewer than six members.
except Exception, e: print str(e) # Print the error.
Python Scripting in Grasshopper
a nifty guide
GHPYTHONLIB: GHCOMP (NODE IN CODE)

GHPythons Node in Code feature allows you to access and execute (almost) any installed
component with a Python script. This is the components module.

Example Script: [Brep | Plane] Component


# Import libraries.
import ghpythonlib.components as ghcomp

# Name the component.


ghenv.Component.Name = "Brep | Plane"
ghenv.Component.NickName = 'Sec'

# Node in Code
sec = ghcomp.BrepXPlane(B, P)
C = sec[0]
P = sec[1]

These do the same thing.


Python Scripting in Grasshopper
a nifty guide
GHPYTHONLIB: PARALLEL

The ghpythonlib also has a module called parallel. It contains a single function, run,
which takes a list of data and a single function that should be called for each item in the list
as its inputs. The run function calls this function on as many threads as there are processors
in your computer, then returns the values in the same order as the input list.
Example Script: [Offset on Srf] Component
from ghpythonlib import parallel as ghpllel
import Rhino

tolerance = Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance

# Function to be executed by parallel.run


def offset_srf(args):
crv, srf = args
crv_length = crv.OffsetOnSurface(srf, D, tolerance)
return [curve for curve in crv_length]
# Run parallel
if P:
args = [[C[i], S[i]] for i in range(len(C))]
OC = ghpllel.run(offset_srf, args, True)
else: pass

These do the same thing.


Python Scripting in Grasshopper
a nifty guide
PARTING THOUGHT

Some things in programming are bad;


they can really make you mad.
Other things just make you swear and curse.
When youre chewing on codes gristle,
dont grumble, give a whistle!
And thisll help things turn out for the best ...

And Always Look on the Bright Side of Life!

You might also like