TouchDesigner ships with Python 3 baked in. Almost every parameter, callback, and DAT can run Python, and a handful of objects (op, me, parent, absTime, …) are auto-imported into every script and expression so you never need to import the td module yourself.

Where Python Lives

Python shows up in five places. Pick the one that matches what you’re doing:

LocationWhen to use it
Parameter expressionsA single one-liner that recalculates each cook. Click a parameter’s mode button to blue, type the expression. See Expressions and Parameters.
Text DATsReusable scripts and modules. Run with the Run Script pulse, or import as a module.
Callback DATsReact to TouchDesigner events. Four flavors: Execute DAT, OP Execute DAT, CHOP Execute DAT, Parameter Execute DAT.
Script OPsDefine an operator’s own behavior via onCook(scriptOp) callback. Used in Script CHOP, Script TOP, Script SOP, Script DAT.
ExtensionsCustom Python classes attached to a COMP that add methods callable as op('myComp').MyMethod().
TextportLive REPL for testing snippets and inspecting state. Open with Alt+T.

Auto-Imported Globals (the td module)

Every Python context in TouchDesigner has these names available without import:

NameWhat it is
opOperator finder. Call as op('name') or op('/abs/path') to fetch any op.
meThe operator currently being evaluated.
parentThe parent COMP. parent(), parent(2), parent.MyComp.
iopInternal Operator Shortcut. Lets a COMP expose internal ops via short names.
iparInternal Parameter Shortcut. Same idea for parameters.
rootThe topmost root op (/).
projectThe current project session.
extExtension lookup, e.g. ext.MyExtension.method().
tduTouchDesigner utility functions (tdu.Position, tdu.remap, …).
modModule-on-demand: mod('myModule').func() reaches into a Text DAT as if it were a Python module.
absTimeAbsolute application time, independent of the timeline.
familiesDict of operator families to their op types.
licenses, monitors, sysinfo, ui, appReflection on the running TouchDesigner.
runSchedule deferred execution.
debugLike print() but prefixes with op + line info.

See The op and me objects for a deeper dive on the most-used three.

DAT Callback Types

Every callback DAT exposes a different set of functions you implement. Drop one and it scaffolds the function signatures for you.

Callback DATFires on
Execute DATProject lifecycle (onStart, onCreate, onExit, frame events)
OP Execute DATWatch one or many ops for events: onCook, onPanelExecute, onChange
CHOP Execute DATA specific CHOP’s channels changing: onValueChange, onOffToOn, onWhileOn
Parameter Execute DATA specific parameter’s value, expression, or mode changing

Example: a Parameter Execute DAT watching a Pulse parameter to trigger an action.

# Parameter Execute DAT, watching myComp.par.Reset (a Pulse)
def onPulse(par):
    print(f'reset fired on {par.owner}')
    op('feedback1').par.reset.pulse()
    return

Common Patterns

# Read a parameter (evaluated)
op('transform1').par.tx.eval()
 
# Write a parameter (constant mode auto-set)
op('transform1').par.tx = 1.0
 
# Set an expression
op('transform1').par.ty.expr = 'absTime.frame * 0.1'
 
# Pulse a Pulse parameter
op('myComp').par.Reload.pulse()
 
# Read a CHOP channel
op('analyze1')['rms']        # the Channel object
op('analyze1')['rms'][0]     # the current sample value
 
# Read a table cell
op('table1')[0, 'name']      # by row index + column name
op('table1')[3, 2]           # by row, col index
 
# Iterate children of a COMP
[c.name for c in op('/project1').children]
 
# Schedule deferred work (in milliseconds)
run("op('flash1').par.opacity = 1.0", delayMilliSeconds=500)
 
# Persistent storage on an op
me.store('lastVal', 42)
me.fetch('lastVal', default=0)

Expression vs. DAT: Which to Use

  • Use an expression when the value should refresh every cook from a small piece of state (current frame, another parameter, a CHOP sample). Cheap, no setup.
  • Use a DAT script when the logic is more than one line, has side effects (writing to multiple ops, calling APIs, mutating state), or runs in response to an event.

Expressions evaluate every cook of the parameter's owner. A heavy expression on a parameter that cooks 60 times a second will cost you. For per-frame logic, prefer an Execute DAT's onFrameStart callback or driving the parameter via a CHOP Export.

Debugging

  • print(x) and debug(x) both write to the Textport (Alt+T).
  • The Errors dialog (Alt+E) collects every active error and warning across the project, with clickable paths.
  • An Error DAT can subscribe to a specific op’s errors and pipe them into a panel.
  • A red ! on an op means it has an error; hover for the message.

What’s Next



(y) Return to Scripting & Architecture | (y) Return to TouchDesigner | (y) Return to Home