Expression vs. Python Editor

It is common to prototype code in the Python Editor, and you may think to do this when you need write some code for an Expression. Beware, though they look deceptively similar, the full Gaffer API is not available in expressions, and references to plugs behave quite differently.

This sometimes leads to an attempt to call something like parent["Sphere"]["radius"].getValue() in an expression, and an exception like the following :

ERROR   [Execution error] Expression1.__execute :"python/Gaffer/PythonExpressionEngine.py", line 88, in execute
line 1, in <module> AttributeError: 'float' object has no attribute 'getValue'

Expressions are nodes

Expressions are nodes and run as part of Gaffer’s compute framework, which means they have the same constraints as all other nodes : during compute, they must read values from a fixed set of input plugs to provide a value for an output plug, nothing else.

They shouldn’t have any side effects and they can’t modify the node graph – you can’t modify the graph while you are performing computations with the graph.

In an expression we hide the actual plugs so that you can’t accidentally modify them using the rest of the API. We do this by getting the values from any plugs you reference, and returning those instead. By the time your code runs, parent is actually just a dictionary of plug values.

Python Editor:

> root["Sphere"]["radius"]
Gaffer.FloatPlug( "radius", defaultValue = 1.0, minValue = 0.0, )
> root["Sphere"]["radius"].getValue()
1

Expression :

> parent["Sphere"]["radius"]
1
> parent["Sphere"]["radius"].getValue()
AttributeError: 'float' object has no attribute 'getValue'

Future changes

In retrospect, it was a mistake to use the same syntax for access to plugs in expressions as in the API. We intend to change this at some point, so that expressions don’t refer to plugs directly.

Instead we are thinking expressions should be more like the OSLCode node, so you add inputs and outputs manually, connect them to external plugs, and then refer to their values via regular variables in the expression. Hopefully this will make it much clearer that although expressions use Python, they have no access to the node graph API.

Useful Links

Leave a Reply