Dynamo
Primer for v2.0
English
English
  • About
  • Introduction
    • What is Dynamo & How Does It Work?
    • Primer User Guide, Dynamo Community & Platform
  • Setup for Dynamo
  • User Interface
    • Workspace
    • Library
  • Nodes and Wires
  • Essential Nodes & Concepts
    • Index of Nodes
    • Geometry for Computational Design
      • Geometry Overview
      • Vector, Plane & Coordinate System
      • Points
      • Curves
      • Surfaces
      • Solids
      • Meshes
    • The Building Blocks of Programs
      • Data
      • Math
      • Logic
      • Strings
      • Color
    • Designing with Lists
      • What's a List
      • Working with Lists
      • Lists of Lists
      • n-Dimensional Lists
    • Dictionaries in Dynamo
      • What is a Dictionary
      • Dictionary Nodes
      • Dictionaries in Code Blocks
      • Revit Use-Cases
  • Custom Nodes & Packages
    • Custom Nodes
      • Custom Node Introduction
      • Creating a Custom Node
      • Publishing to Your Library
    • Packages
      • Package Introduction
      • Package Case Study - Mesh Toolkit
      • Developing a Package
      • Publishing a Package
      • Zero-Touch Importing
  • Dynamo for Revit
    • The Revit Connection
    • Selecting
    • Editing
    • Creating
    • Customizing
    • Documenting
  • Dynamo for Civil 3D
    • The Civil 3D Connection
    • Getting Started
    • Node Library
    • Sample Workflows
      • Roads
        • Light Pole Placement
      • Land
        • Service Placement
      • Utilities
        • Rename Structures
      • Rail
        • Clearance Envelope
      • Surveying
        • Point Group Management
    • Advanced Topics
      • Object Binding
      • Python and Civil 3D
    • Dynamo Player
    • Useful Packages
    • Resources
  • Dynamo in Forma Beta
    • Set Up Dynamo Player in Forma
    • Add and Share Graphs in Dynamo Player
    • Run Graphs in Dynamo Player
    • Dynamo compute service differences with Desktop Dynamo
  • Coding in Dynamo
    • Code Blocks and DesignScript
      • What's a Code Block
      • DesignScript Syntax
      • Shorthand
      • Functions
    • Geometry with DesignScript
      • DesignScript Geometry Basics
      • Geometric Primitives
      • Vector Math
      • Curves: Interpolated and Control Points
      • Translation, Rotation, and Other Transformations
      • Surfaces: Interpolated, Control Points, Loft, Revolve
      • Geometric Parameterization
      • Intersection and Trim
      • Geometric Booleans
      • Python Point Generators
    • Python
      • Python Nodes
      • Python and Revit
      • Setup Your Own Python Template
    • Language Changes
  • Best Practices
    • Graph Strategies
    • Scripting Strategies
    • Scripting Reference
    • Managing Your Program
    • Efficiently Working With Large Data Sets In Dynamo
  • Sample Workflows
    • Getting Started Workflows
      • Parametric Vase
      • Attractor Points
    • Concept Index
  • Developer Primer
    • Build Dynamo from Source
      • Build DynamoRevit from Source
      • Managing and Updating Dependencies in Dynamo
    • Developing for Dynamo
      • Getting Started
      • Zero-Touch Case Study - Grid Node
      • Executing Python Scripts in Zero-Touch Nodes (C#)
      • Going Further with Zero-Touch
      • Advanced Dynamo Node Customization
      • Using COM (interop) types in Dynamo Packages
      • NodeModel Case Study - Custom UI
      • Updating your Packages and Dynamo Libraries for Dynamo 2.x
      • Updating your Packages and Dynamo Libraries for Dynamo 3.x
      • Extensions
      • Defining Custom Package Organization for Dynamo 2.0+
      • Dynamo Command Line Interface
      • Dynamo Integration
      • Developing For Dynamo For Revit
      • Publish a Package
      • Build a Package from Visual Studio
      • Extensions as Packages
    • Pull Requests
    • Testing Expectations
    • Examples
  • Appendix
    • Frequently Asked Questions
    • Visual Programming and Dynamo
    • Resources
    • Release Notes
    • Useful Packages
    • Example Files
    • Host Integration Map
    • Download PDF
    • Dynamo Keyboard Shortcuts
Powered by GitBook
On this page
Edit on GitHub
Export as PDF
  1. Developer Primer
  2. Developing for Dynamo

Executing Python Scripts in Zero-Touch Nodes (C#)

PreviousZero-Touch Case Study - Grid NodeNextGoing Further with Zero-Touch

Last updated 2 years ago

Executing Python Scripts in Zero-Touch Nodes (C#)

If you are comfortable writing scripts in Python and want more functionality out of the standard Dynamo Python nodes, we can use Zero-Touch to create our own. Let's start with a simple example that allows us to pass a python script as a string to a Zero-Touch node where the script is executed and a result is returned. This case study will build on the walk-throughs and examples in the Getting Started section, please refer to those if you are completely new to creating Zero-Touch nodes.

A Zero-Touch node that will execute a Python script string

Python Engine

This node relies on an instance of the IronPython scripting engine. To do this, we need to reference a few additional assemblies. Follow the steps below to setup a basic template in Visual Studio:

  • Create a new Visual Studio class project

  • Add a reference to the IronPython.dll located in C:\Program Files (x86)\IronPython 2.7\IronPython.dll

  • Add a reference to the Microsoft.Scripting.dll located in C:\Program Files (x86)\IronPython 2.7\Platforms\Net40\Microsoft.Scripting.dll

  • Include the IronPython.Hosting and Microsoft.Scripting.Hosting using statements in your class

  • Add a private empty constructor to prevent an additional node from being added to the Dynamo library with our package

  • Create a new method that takes a single string as an input parameter

  • Within this method we will instantiate a new Python engine, and create an empty script scope. You can imagine this scope as the global variables within an instance of the Python interpreter

  • Next, call Execute on the engine passing the input string and the scope as parameters

  • Finally, retrieve and return the results of the script by calling GetVariable on the scope and passing the name of the variable from your Python script that contains the value you are trying to return. (See the example below for further details)

The following code provides an example for the step mentioned above. Building the solution will create a new .dll located in the bin folder of our project. This .dll can now be imported into Dynamo as part of a package or by navigating toFile < Import Library...

using IronPython.Hosting;
using Microsoft.Scripting.Hosting;

namespace PythonLibrary
{
    public class PythonZT
    {
        // Unless a constructor is provided, Dynamo will automatically create one and add it to the library
        // To avoid this, create a private constructor
        private PythonZT() { }

        // The method that executes the Python string
        public static string executePyString(string pyString)
        {
            ScriptEngine engine = Python.CreateEngine();
            ScriptScope scope = engine.CreateScope();
            engine.Execute(pyString, scope);
            // Return the value of the 'output' variable from the Python script below
            var output = scope.GetVariable("output");
            return (output);
        }
    }
}
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

cube = Cuboid.ByLengths(10,10,10);
volume = cube.Volume
output = str(volume)

Multiple Outputs

One limitation of the standard Python nodes is that they only have a single output port so if we wish to return multiple object we must construct a list and retrieve each object in. If we modify the example above to return a dictionary, we can add as many output ports as we want. Refer to the Returning Multiple Values section in Going Further With Zero-Touch for more specifics on dictionaries.

This node is allowing us to return both the cuboid's volume and its centroid.

Let's modify the previous example with these steps:

  • Add a reference to DynamoServices.dll from the NuGet package manager

  • In addition to the previous assemblies include System.Collections.Generic and Autodesk.DesignScript.Runtime

  • Modify the return type on our method to return a dictionary which will contain our outputs

  • Each output must be individually retrieved from the scope (consider setting up a simple loop for larger sets of outputs)

using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
using System.Collections.Generic;
using Autodesk.DesignScript.Runtime;

namespace PythonLibrary
{
    public class PythonZT
    {
        private PythonZT() { }

        [MultiReturn(new[] { "output1", "output2" })]
        public static Dictionary<string, object> executePyString(string pyString)
        {
            ScriptEngine engine = Python.CreateEngine();
            ScriptScope scope = engine.CreateScope();
            engine.Execute(pyString, scope);
            // Return the value of 'output1' from script
            var output1 = scope.GetVariable("output1");
            // Return the value of 'output2' from script
            var output2 = scope.GetVariable("output2");
            // Define the names of outputs and the objects to return
            return new Dictionary<string, object> {
                { "output1", (output1) },
                { "output2", (output2) }
            };
        }
    }
}

We have also added an additional output variable (output2) to the sample python script. Keep in mind that these variables can use any legal Python naming conventions, output has been used strictly for the sake of clarity in this example.

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

cube = Cuboid.ByLengths(10,10,10);
centroid = Cuboid.Centroid(cube);
volume = cube.Volume
output1 = str(volume)
output2 = str(centroid)

The Python script is returning the variable output, which means we will need an output variable in the Python script. Use this sample script to test the node in Dynamo. If you have ever used the Python node in Dynamo the following should look familiar. For more information check out the .

Python section of the primer
A Zero-Touch node that will execute a Python script string
This node is allowing us to return both the cuboid's volume and its centroid.