Close

Category:Python

Python In TouchDesigner

TouchDesigner uses Python for scripting tasks. A custom Python build is included, with most of the features of a standard Python installation and a huge number of tools and utilities specific to working in the software.

In addition, numerous working examples can be seen by selecting Help -> Python Examples in the TouchDesigner UI.

Learning Python

If you don't know Python, here are some good resources for learning:

Python Classes and Modules Available in TouchDesigner

TouchDesigner includes all the modules in a standard Python installation plus the following:

td: TouchDesigner's Main Python Module

All td module members and methods are available in scripts, expressions, and the textport. There is no need to import the module or its members explicitly. This is especially important in expressions, which don't allow import statements.

The following can be found in the td module:

  • Main TouchDesigner utilities - the most basic starting points for interacting with TouchDesigner, such as me and op().
  • TouchDesigner Python helper classes - important helper objects used to organize functions and information pertaining to a specific part of TouchDesigner.
  • Operator related classes - every Operator in TouchDesigner has an associated Python class in the td module. Their wiki pages can be accessed by clicking on the Python Help button in their parameter dialog. There are also a number of associated Python objects that are used when working with Operators.
  • Useful standard Python modules - the td module also automatically imports a number of helpful standard modules (e.g. math), allowing them to be accessed in expressions through their namespace.

TouchDesigner Utility Modules

TouchDesigner also contains utility modules for advanced Python programming. Utility modules are not imported into the td module automatically. Instructions for their use can be found on their wiki pages.

3rd Party Packages

TouchDesigner includes a number of 3rd party Python packages that are generally useful when working with the software. These are not included in the td module so must be imported explicitly.

Installing Custom Python Packages

Part of the great power of Python is its access to the countless number of modules that have been created. If you want to use modules that are not included in the above, use the following steps:

Windows

  1. Install a parallel copy of the same version of Python to the hard disk. The current version of Python shipped with TouchDesigner is 3.9. It can be found here. Use the most recent subversion of 3.9.
    1. Alternatively, you can use a Python package and environment manager, such as Anaconda.
  2. Install the package to the parallel python installation, following its normal installation procedure.
  3. Launch Python and import the module manually to make sure there are no errors outside of the TouchDesigner context.

Once the module is successfully installed, you can import it in TouchDesigner following those next steps:

Under the Edit->Preferences menu, tick "Add External Python to Search Path". You can add the search path by modifying the Preference labelled "Python 32/64 bit Module Path". Multiple paths are separated by semicolons (;).

Finally you can modify the search path directly by either modifying the system environment variable PYTHONPATH or by firing an Execute DAT onStart() with the code snippet below.

import sys
mypath = "C:/Python39/Lib/site-packages"
if mypath not in sys.path:
	sys.path = [mypath] + sys.path

This script will prepend your custom Python install site-packages folder to your PATH. Prepending will make sure that your custom packages, when being imported, will have priority over any other package with a matching package name found in the path. If the package is not found in the custom path, but a package of the same name is found in the TouchDesigner Python site-packages folder then it will fall back on this package.

Users can also import packages from Python installations that weren't installed with the official Python installer but with alternative Python package and environment managers, such as Anaconda.

Examples of other useful Python modules are here. Unofficial precompiled modules found on Christoph Gohlke's website.

MacOS

On MacOS, use Homebrew to manage your Python installations. Follow the instructions on Homebrew's website to get started.

When Homebrew is installed, you can use the command brew install python to install the latest version of Python on your system. To use a specific version, such as matching TouchDesigner's Python 3.9, add @3.9 after python.

Intel Macs

On Intel's Macs, your default Homebrew path should be /usr/local/bin/brew

ARM Macs

On ARM's Macs, your Homebrew path should be /opt/homebrew/bin/brew, for the native ARM homebrew. That is, when using the default Homebrew install command.

NOTE: In some cases, you might want to run Homebrew Rosetta. It is required if you are using the non-native / Intel TouchDesigner build and require a Python version that is not available as an ARM installer on MacOS.

To install Homebrew Rosetta, use the following command: arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)". Your Homebrew Rosetta path should be /usr/local/bin/brew.

If you have both Homebrew versions installed on your system, it is advised to add an alias for the Homebrew Rosetta installation. Use the following command in your terminal alias ibrew="arch -x86_64 /usr/local/bin/brew" where ibrew stands for Intel Brew. You can add this alias to your terminal profile so that it is persistent.

You can now use either brew install YOUR_APP_NAME or ibrew install YOUR_APP_NAME to install ARM or Intel formulas or casks respectively.

Continue with your python installation, matching TouchDesigner's Python, as described at the top of this MacOS section. Remember, if you followed the previous steps: when your are using the ARM native TouchDesigner build, use brew, if it's the Intel build running with Rosetta, use ibrew.

It can also be useful to add extra aliases, and precede them with an i when they are related to Intel / Rosetta, for Python itself, and pip:

alias iPY39=/usr/local/opt/python@3.9/bin/python3
alias iPIP39=/usr/local/opt/python@3.9/bin/pip3

Now, all you have to do is install your custom (Intel) Python 3.9 packages using iPIP39 install YOUR_PACKAGE_NAME.

Once the module is successfully installed, you can import it in TouchDesigner following those next steps:

Under the Edit->Preferences menu, tick "Add External Python to Search Path". You can add the search path by modifying the Preference labelled "Python 32/64 bit Module Path". Multiple paths are separated by semicolons (;).

Finally you can modify the search path directly by either modifying the system environment variable PYTHONPATH or by firing an Execute DAT onStart() with the code snippet below.

import sys
mypath = "/usr/local/lib/python3.9/site-packages" # TIP: This path is printed out in the terminal when installing this Python version with Homebrew
if mypath not in sys.path:
	sys.path = [mypath] + sys.path

This script will prepend your custom Python install site-packages folder to your PATH. Prepending will make sure that your custom packages, when being imported, will have priority over any other package with a matching package name found in the path. If the package is not found in the custom path, but a package of the same name is found in the TouchDesigner Python site-packages folder then it will fall back on this package.

Python Gotchas

There are a few things in standard Python that can trip you up in TouchDesigner. If you find anything that's not included here, post in the forum!

  • Some TouchDesigner objects (especially parameters and CHOP channels) will try to act as the correct data type for their context. For example, a Float parameter object (myOp.par.Float1) will act like a floating point number in most cases, but it is still a parameter object. For example round(myOp.par.Float1) will not work. To get the actual value of a parameter or channel, use its .eval() method. If you think you may be encountering this problem, you can tell the difference by using the repr function. For example repr(myOp.par.Float1) will show that this is a parameter and not a number.
  • same goes with operator parameter types. if a parameter is a path to a CHOP, n.par.Chop usually works, but to be safe, n.par.Chop.eval() always works.
  • subprocess.Popen doesn't work with file-like objects. See this forum post for details.
  • Python threads don't have access to TouchDesigner objects. Search "threading" in the forum to see some workarounds.

More In The Python Category