pythonModule.py
script is responsible for the Services subscription in the Python environmentpythonUtils.py
script is an utility script usable by the user Python scriptpythonModule
element. For example:<pythonModule name="FlightManagementSystem">By default these modules use a UDP communication, but it is possible to specify if the communication uses TCP or UDP using the
protocol
attribute in the pythonImplementation
element:udp
value specifies that the communication uses UDPtcp
or tcpBlocking
value specifie that the communication uses TCP. See Python TCP modules for more information<pythonModule name="PublishModule" > <pythonImplementation path="pythonAppli" protocol="tcp"> <defaultSendEntryPoint method="publish" /> </pythonImplementation> </pythonModule>
pythonImplementation
element declares the Python script file which implements the script, and specifies the associated properties.path
: refer to the name of the file (without the ".py" extension) which implements the Python script. The path of this file is by default relative to the application.xml
file which declares the moduleinputPort
, inputSize
, outputPort
, and outputSize
: define the ports which will be used to communicate between the java application and the Python Script[2]
wait
: the optional duration to wait after each Java - Python dialog. By default the duration will be specified as 10 ms if not definedpythonEnumAsString
: an optional boolean to specify that enumeration values should be sent as names to the Python module rather than their index. See Enumerations as String for more informationclassName
: the optional name of the Python class to call. By default the name is derived from the name of the Python module. See Python class name for more informationprotocol
: specifies the protocol (default is "udp"). Allows to use TCP modules rather than UDP. See declaration for more informationhost
: specifies the host. By default if not specified the host will be the localhost (127.0.0.1), but it is possible to specify the value of the host explicitly. See also host for more informationcompatibility
: Allows to set a compatibility for an older version of the Python modules. See Python compatibility for more informationhost
parameter for the pythonImplementation
element allows to specify the host for the Java to/from Python communication. By default if not specified the localhost (127.0.0.1) will be used.pythonQueue
child element allows to specify how the services notifications are handled at the python level. This element has the following attributes (all optional):queueSize
: the optional size of the queue (used for all services notifications by default)publishQueueSize
: the optional size of the queue for publish Service notificationseventQueueSize
: the optional size of the queue for event and request services notifications. Note that the event queue has priority on the publish queue<pythonImplementation path="pythonAppli" inputSize="1024" outputSize="1024"> <pythonQueue publishQueueSize="20" eventQueueSize="10" /> </pythonImplementation>
<pythonModule name="FlightManagementSystem" > <pythonImplementation path="pythonAppli" inputPort="6000" outputPort="6005" inputSize="1024" outputSize="5000"/> </pythonModule>Another example, where available free local ports are used for
inputPort
and outputPort
, and 1024 is used for both inputSize
and outputSize
:<pythonModule name="FlightManagementSystem" > <pythonImplementation path="pythonAppli" /> </pythonModule>
inputSize
represents the size of the buffer from Java to Python. outputSize
represents the size of the buffer from Python to Java:outputSize
is too small.
<services> <publish name="position" > <data name="latitude" type="float" /> <data name="longitude" type="float" /> <data name="altitude" type="float" /> </publish> </services>We may have the following content exchanged between Java and Python:
position=latitude:1.23^longitude:0.45^altitude:1200
It is possible to change the default value of the separator to be any character (or even a string having more than one character), including unicode character. This may be useful if string data sent or received by the Python script contain the default separator character.<pythonImplementation ... separator="!" >
<pythonImplementation ... separator="!!" >
<pythonImplementation ... separator="°" >
def method_name(self, pythonUtils):with
method_name
being the name defined for the Start entry point. The method will be called once after the framework has been started.<pythonModule name="FlightManagementSystem" > <pythonImplementation path="pythonAppli" inputPort="6000" outputPort="6005" inputSize="1024" outputSize="1024"> <initEntryPoint method="init" /> </pythonImplementation> </pythonModule>
def method_name(self, pythonUtils):with method_name being the name defined for the Start entry point. The method will be called once after the framework has been started.
<pythonModule name="FlightManagementSystem" > <pythonImplementation path="pythonAppli" inputPort="6000" outputPort="6005" inputSize="1024" outputSize="1024"> <startEntryPoint method="start" /> </pythonImplementation> </pythonModule>
defaultReceiveEntryPoint
element defines the default method which will be called by default when being notified by a Service.<pythonModule name="FlightManagementSystem" > <pythonImplementation path="pythonAppli" inputPort="6000" outputPort="6005" inputSize="1024" outputSize="1024"> <defaultReceiveEntryPoint method="receive" /> </pythonImplementation> <interfaces> <push service="service1" /> <subscribe service="service2" /> </interfaces> </pythonModule>The method must have the following signature:
def method_name(self, pythonUtils, serviceName):
defaultSendEntryPoint
element defines the default method which will be called by default when invoking automatically a publish Service[5]
<send>(ServiceInstance service)
. The method will be called each time a Service invoked automatically is invoked (just before sending its result).<pythonModule name="FlightManagementSystem" > <pythonImplementation path="pythonAppli" inputPort="6000" outputPort="6005" inputSize="1024" outputSize="1024"> <defaultSendEntryPoint method="send" /> </pythonImplementation> <interfaces> <push service="service1" /> <subscribe service="service2" /> </interfaces> </pythonModule>It can be used to perform computations before invoking the Service (for example, setting values to datas).
def method_name(self, pythonUtils, serviceName):
<pythonModule name="FlightManagementSystem" > <pythonImplementation path="pythonAppli" inputPort="6000" outputPort="6005" inputSize="1024" outputSize="1024"> <defaultReceiveEntryPoint method="receive" /> <defaultSendEntryPoint method="invoke" /> </pythonImplementation> <interfaces> <push service="service1" > <entryPoint method="subscribe1" /> </push> <subscribe service="service2" > <entryPoint method="subscribe2" /> </subscribe> </interfaces> </pythonModule>
myPythonAppli.py
, then the path parameter must be myPythonAppli
, and the class defined in the module must be named MyPythonAppli
.<pythonModule name="FlightManagementSystem" id="1" > <pythonImplementation path="pythonAppli" inputPort="6000" outputPort="6005" inputSize="1024" outputSize="1024"/> </pythonModule>and:
from pythonUtils import PythonUtils class PythonAppli:However, it is possible to specify the name of the class to call in the module by using the
className
parameter.<pythonModule name="FlightManagementSystem" id="1" > <pythonImplementation path="pythonAppli" className="FMS" inputPort="6000" outputPort="6005" inputSize="1024" outputSize="1024"/> </pythonModule>and:
from pythonUtils import PythonUtils class FMS:
pythonEnumAsString
property specifies that the state names should be sent instead. Note that this can also be configured with the framework property of the same name.
PythonUtils
class in the pythonUtils
modulepythonModule.py
and pythonUtils.py
scripts must change when the communication between Java and Python is upgraded.pythonModule.py
script check if its own version is compatible with the version proviced by Java. This means that you normally should replace the pythonModule.py
and pythonUtils.py
scripts if the Python modules version changes.
pythonModule.py
scriptpythonUtils.py
scriptpythonUtils.py
script utility has the following utility methods:def getService(self, name):
: get a Service with its namedef setValue(self, service, name, value):
: set a Data value for a Servicedef send(self, serviceName):
: invoke a Servicedef echo(self, content):
: print the value of an element[7]
print(content)
would not print the content in many casesdef err(self, message):
: print a message on the system.err Stream
value = service[data_name]
def <method_name>(self, pythonUtils):This method will be called when the module is initialized, during the framework initialization.
<pythonImplementation path="pythonAppli"> <initEntryPoint method="myInitMethod" /> </pythonImplementation>
def <method_name>(self, pythonUtils):This method will be called when the module is started, during the framework effective start.
<pythonImplementation path="pythonAppli"> <startEntryPoint method="myStartMethod" /> </pythonImplementation>
def <method_name>(self, pythonUtils, serviceName):This method will be called for a publish Services and event Services called cyclically.
<pythonImplementation path="pythonAppli"> <defaultSendEntryPoint method="myCyclicMethod" /> </pythonImplementation>
subscribe
method with the following signature[9]
subscribe
name is the default name for all service subscriptions. But it is possible to change the method name for all Services or just for one Service. See def subscribe(self, pythonUtils, serviceName):This method will be called when the module is notified from the invocation of any Service. To detect which service is at the origin of the notification, you can perform:
# to get the service itself service = pythonUtils.getService(serviceName)The datas of the service can be retrieved with:
data = service[theDataName]
To set a value for a data for any Service for which the module is a provider, you can perform:
pythonUtils.setValue(service, theDataName, theDataValue)
To invoke a Service for which the module is a provider, you can perform:
pythonUtils.send(serviceName)
FlightManagementSystem
module:position
publish servicedirectTo
event servicecomputeFlightPlan
request-response service<pythonModule name="FlightManagementSystem" > <pythonImplementation path="pythonAppli"/> <interfaces> <subscribe service="position" /> <eventReceived service="directTo"/> <requestReceived service="computeFlightPlan"/> </interfaces> </pythonModule>Another way to specify the Python module is to explictly specify the ports and port sizes for the Java / Python communication:
<pythonModule name="FlightManagementSystem" > <pythonImplementation path="pythonAppli" inputPort="6000" outputPort="6005" inputSize="1024" outputSize="1024"/> <interfaces> <subscribe service="position" /> <eventReceived service="directTo"/> <requestReceived service="computeFlightPlan"/> </interfaces> </pythonModule>
from pythonUtils import PythonUtils class PythonAppli: def subscribe(self, pythonUtils, serviceName): service = pythonUtils.getService(serviceName) if serviceName == "position": // get position ... elif serviceName == "directTo": // compute directTo ... elif serviceName == "computeFlightPlan": // compute FlightPlan and sends the response ...
print(content)
would not print the content in many casessubscribe
name is the default name for all service subscriptions. But it is possible to change the method name for all Services or just for one Service. See Copyright 2017-2020 Dassault Aviation. All Rights Reserved. Documentation and source under the LGPL v3 licence