Nodes/Pixar's OpenUSD/USD Python Script
ComfyUI Node

USD Python Script

The escape hatch when no node does what you need

By cjhosken·Created 3 months ago·Updated 2 months ago· 9
USD Python Script
  • usd_stage
  • USD
script# The stage is available as 'stage' # Example: # prim = stage.DefinePrim('/MyPrim', 'Xform')

USD is enormous, and no custom node pack can wrap all of it. USD Python Script is how the ComfyUI-OpenUSD pack admits that: it runs arbitrary Python against your stage with the full pxr USD API in scope. Whatever the dedicated nodes can't express - building geometry from scratch, authoring a material network, querying the stage, doing something the author never imagined - you can just write it. It's the "Python Script" node pattern, pointed at a USD stage.

Why you'd reach for it

The pack covers the common cases with dedicated nodes: transform, color, attributes, save, view. The long tail is infinite. You want to procedurally generate a grid of cubes? Define prims in a loop. You want to set a custom metadata dict on a prim? That's a couple of lines of pxr. You want to walk the stage and print every prim of a given type, or flip the up-axis, or build a material with UsdShade? All of it is a script. Every serious USD user eventually ends up reaching for the API directly; this node is that reach from inside the graph.

How it works

The node takes your stage and execs your script with two names in scope: stage (the stage object) and Usd (the pxr.Usd module). Your script mutates stage in place, and that same stage object comes out the USD output. If your script raises, the error is printed to the console and re-raised, so a broken run fails the workflow with a real traceback instead of silently passing a half-edited stage.

The default text is a commented template showing the entry points:

# The stage is available as 'stage'
# prim = stage.DefinePrim('/MyPrim', 'Xform')

One scoping quirk worth knowing: the exec runs in a fresh namespace, so you can't return a value out of the script, and variables you define don't leak back to the node. To get data out, author it onto the stage (set an attribute, define a prim) and read it with a Get/USD to Text node downstream, or print() and read the console. You also only get Usd for free - if you want UsdGeom, UsdShade, Gf, or Sdf, import them at the top of your script:

from pxr import UsdGeom, UsdShade, Gf
mesh = UsdGeom.Mesh.Define(stage, "/MyPrim")
mesh.CreatePointsAttr().Set([Gf.Vec3f(0,0,0), Gf.Vec3f(1,0,0), Gf.Vec3f(0,1,0)])

Inputs and output

  • usd_stage - the USD stage to operate on (note the name differs from the usual USD socket).
  • script - multiline Python, run with stage and Usd in scope.
  • Output: the same USD stage, mutated.

Install

Part of the cjhosken/ComfyUI-OpenUSD pack. ComfyUI Manager, search "ComfyUI-OpenUSD", or:

cd ComfyUI/custom_nodes
git clone https://github.com/cjhosken/ComfyUI-OpenUSD

Restart. Backend deps are usd-core==26.5 (the heavy one - this is where all the pxr API comes from), plus numpy, trimesh, pygltflib. No model downloads.

Troubleshooting

  • NameError: name 'UsdGeom' is not defined - expected. Only stage and Usd are preloaded; import the submodules yourself.
  • "return outside function" or nothing coming out - you can't return from the script. Author results onto the stage instead.
  • The workflow fails with your traceback - that's the design. The error is printed to the ComfyUI console and the run stops; fix the script, not the node.

And the pack-level caveat that applies extra here: v0.1.1, no track record, and this node is arbitrary Python executing with your user permissions. That's the same power model as every ComfyUI custom node (the ecosystem runs on it), so it's not a new risk - but it's a reminder to only install packs you trust. The stage-mutation design is simple and predictable; the surprises will come from your own scripts, not the node.

Category3d/usd/utils

Inputs (2)

NameTypeDefaultDescription
usd_stageUSD
scriptSTRING# The stage is available as 'stage' # Example: # prim = stage.DefinePrim('/MyPrim', 'Xform')

Outputs (1)

NameTypeDescription
USDUSD