Appearance
Python script
Runs your own Python code (CPython embedded through pythonnet) for every message that reaches the component. Use it for transformations or when you need Python packages installed on the host.
Pins
| Pin | Kind | Types | Description |
|---|---|---|---|
| Input | input | any | The data from the previous component. Its type is the type of the input connection. |
| Output | output | any | Whatever the script passes to services.Next. The template creates an object of the output connection's type. |
Configuration
| Field | Type | Default | Description |
|---|---|---|---|
Script | code (Python) | empty | The user script: a function execute(metaData, inputData) plus any imports, functions and classes you need. Empty means the generated template is used. |
Behaviour
Before your code the component generates a Python class for every type of the flow (same class and property names as in the flow, e.g.
inputData.Name), the classesFlowMetaData,NoInputData,AnyInputDataandViaFileInfo, and the globalservices.base64,datetime,uuidand theviaductapackage are already imported. This part is hidden in the editor; your code starts with the#viaducta.python.codemarker, and the line numbers of errors and of the debugger are the lines of your script.The script is executed once when the flow starts (module-level code runs then); for every message the component calls
execute(metaData, inputData), whereinputDataalready is an instance of the input connection's class (NoInputDatawhen nothing is connected). Module-level variables keep their values between messages. Messages are processed one at a time per component.The generated template:
pythondef execute(metaData: FlowMetaData, inputData: Customer): outputData = CustomerDto() services.Next(metaData, outputData)CustomerDtois the output connection's type; without an output connection the template callsservices.Next(metaData, inputData).servicesis the component's flow service (IFlowService) with the C# member names, the same services a C# script has:services.Log,services.Messaging,services.Settings,services.Component,services.Flow,services.Profiler,services.Batches,services.Storage,services.Repositoryand the rest. Theviaductapackage (see Notes) gives the editor their types.services.Next(metaData, obj)sendsobjto the components connected toOutput;objmust be an instance of one of the generated flow classes. It can be called zero, one or many times.services.Next(metaData, obj, connectionId)sends to one connection only. The next components run on a separate task, soNextreturns before they finish.Frequently used services:
services.Log.Information("...")(alsoDebug,Warning,Error,Fatal) writes to the flow log.services.Messaging.Information("...")(alsoWarning,Error,Trace) writes to the designer console;UpdateStatusMessage("..."),UpdateProgress(0.5)(0 to 1),StopProgress()andClear()update the component.services.Settings.Get("Package", "Name")reads an expression setting.services.Component.Id/.Name;services.Profiler.UpdateRecordsProduced(services.Component.Id, 1).services.Batches.Begin(metaData, "label")opens a batch:with services.Batches.Begin(metaData, fileName) as batch:send the records withbatch.MetaDataand callbatch.Complete(); leaving the block withoutComplete()fails the batch.services.HandleExceptionAsync(metaData, inputData, ex)hands a caught exception to the flow's error handling and carries on.
List properties are
ViaProxyArrayobjects: index,len(),in, iteration,append,extend, assignment by index anddelare written through to the .NET list. Date properties are returned asdatetime.datetime. Decimal properties are returned asfloatand acceptfloat,intanddecimal.Decimal(aDecimalkeeps its full precision).Leading tabs are converted to 4 spaces before execution; don't mix tabs and spaces differently inside a block.
An exception that leaves
executegoes to the flow's error handling asPythonScriptException: the message isValueError: ..., the stack trace is the Python traceback from your code on, and the error line is marked in the editor.In debug mode the script is traced line by line while
executeruns: the debugger stops before a line runs and shows its local variables (flow objects and other .NET objects as .NET objects, Python values as a dump of at most 1000 values). Module-level code is not traced.
Notes
- Editor support: the
viaductapackage (viaducta-<version>-py3-none-any.whl, built with theViaducta.Pythonproject) contains type stubs forservicesand everything it returns. Install it into the Python of your editor (pip install viaducta-...whl) for completion and type checking outside the designer. The host doesn't need it: the component brings its own copy and puts it first onsys.path. printoutput goes to the host's stdout, not to the designer; useservices.Messaging.Informationorservices.Log.- The Python configured as
Python.RuntimeDll(defaultpython312.dll, 3.11 or newer) must be available on the host; extra packages must be installed into that Python. - The Python engine is shared by the whole host process: it starts once and stays up until the process ends, stopping a component only releases its own module.
- The template is generated from the connections that exist when it is created; connect first, then open the editor (or clear the script).
Example
Input connection type Customer, output connection type CustomerDto:
python
#viaducta.python.code
import re
def execute(metaData: FlowMetaData, inputData: Customer):
if not inputData.Email:
return # filter: nothing is sent on
outputData = CustomerDto()
outputData.Name = inputData.Name.title()
outputData.Phone = re.sub(r"\D", "", inputData.Phone or "")
services.Messaging.UpdateStatusMessage("Last: " + inputData.Email)
services.Next(metaData, outputData)Database reader → Python script → Json serializer → File writer