DS2 modules, running
in SAS Micro Analytic Service, can publish and execute Python modules.
Note that Python 2.7
or Python 3.4 must be available for SAS Micro Analytic Service to
load. If both are available, SAS Micro Analytic Service loads Python
3.4. See
Python Support in SAS Micro Analytic Service, for information about installing Python and configuring
the environment variables necessary to allow Python to run embedded
in SAS Micro Analytic Service. As is the case when calling any package
from DS2, it is recommended that you always check return codes where
available, and return any error codes using an output argument from
your DS2 method.
Each package instance
represents exactly one module revision. You can create as many instances
as desired, allowing multiple modules to be used. The module name
(or the Python script name) is given as a package constructor argument.
The constructor automatically sets up user and module contexts to
house the instance.
Here are some operations
that a DS2 module would typically perform.
Instantiate the following
DS2 package:
py = _new_ maspy(“myPythonScript”);
Calling publish() compiles
your Python script and creates the revision. The Python code is passed
as a string in the first argument. A list of argument names is required
by Python and is passed as an array of strings in the second argument.
As is the case with any method signature in SAS Micro Analytic Service,
all of the input arguments must precede the output arguments in the
list.
rc = py.publish(python_script, arguments, numinputs);
Call setType methods
to set input values before executing the script. Because these setters
store arguments by name, they can be called in any order and will
insert the values in the correct positions:
py.setDouble(“airflow”, sensor_maf);
Since the DS2 package
instance represents a single revision, the execute() method needs
no arguments.
After execution, call
getters to retrieve the results.
score = py.getDouble(“credit_score”);
Scalar argument setters
are of the form:
return_code = set<type>(name, value)
Scalar argument getters
are of the form:
Array argument setters
are of the form:
rc = set<type>Array(name, array-value)
Array argument getters
are of the following form.
Note: DS2 passes arrays and output
values by reference.
get<type>Array(name, array-value, rc)
The following setOut
methods reserve space in the argument list for output arguments.
rc = setOut<type>(name)
rc = setOut<type>Array(name)
Note: If an array is not originally
allocated, or if it is allocated with insufficient size, it will be
allocated or reallocated with sufficient size to accommodate DS2.
The example below assumes
that you have declared your package as py:
dcl package pymas py;
dcl int rc;
dcl bigint result;
rc = py.publish(python_script, symbols, number_of_inputs);
py.setString(“inString”, “A string”);
rc = py.setOutLong(“outLong”);
py.execute()
result = py.getLong(“outLong”);
The requestInterrupt(userContext,
moduleContext, revision, entryPoint) method can be used to halt the
execution of a runaway module or method, such as a method containing
an infinite loop. It can be used to halt the execution of DS2 modules,
Python modules, or DS2 modules that call Python. When interrupting
a Python module, the entryPoint parameter is ignored, since a Python
module represents one entire Python script.
The complete set of
DS2 package methods follows, where rc
is
the integer return code, and py
is the package
instance.
Methods for Python module
management and execution:
rc = py.publish(python_script, arguments, numinputs);
rc = py.remove();
rc = py.isLoaded(); // returns true is Python is available and false otherwise
rc = py.getModuleContextID();
rc = py.getRevisionNumber();
rc = py.setTimeZone(time_zone_identifier);
rc = py.execute();
Scalar argument setters:
rc = py.setString(argument_name, value);
rc = py.setBool(argument_name, value);
rc = py.setLong(argument_name, value);
rc = py.setInt(argument_name, value);
rc = py.setDouble(argument_name, value);
rc = py.setDateTime(argument_name, value);
rc = py.setDate(argument_name, value);
rc = py.setTime(argument_name, value);
Scalar argument getters:
string_value = py.getString(argument_name);
int_value = py.getBool(argument_name);
long_value = py.getLong(argument_name);
int_value = py.getInt(argument_name);
double_value = py.getDouble(argument_name);
date_time_value = py.getDateTime(argument_name);
date_value = py.getDate(argument_name);
time_value = py.getTime(argument_name);
Scalar output argument
setters:
rc = py.setOutString(argument_name);
rc = py.setOutBool(argument_name);
rc = py.setOutLong(argument_name);
rc = py.setOutInt(argument_name);
rc = py.setOutDouble(argument_name);
rc = py.setOutDateTime(argument_name);
rc = py.setOutDate(argument_name);
rc = py.setOutTime(argument_name);
Array argument setters:
rc = py.setStringArray(argument_name, string_array);
rc = py.setBoolArray(argument_name, integer_array);
rc = py.setLongArray(argument_name, bigint_array);
rc = py.setIntArray(argument_name, integer_array);
rc = py.setDoubleArray(argument_name, double_array);
rc = py.setDateTimeArray(argument_name, date_time_array);
rc = py.setDateArray(argument_name, date_array);
rc = py.setTimeArray(argument_name, time_array);
Array argument getters:
py.getStringArray(argument_name, string_array, rc);
py.getBoolArray(argument_name, integer_array, rc);
py.getLongArray(argument_name, bigint_array, rc);
py.getIntArray(argument_name, integer_array, rc);
py.getDoubleArray(argument_name, double_array, rc);
py.getDateTimeArray(argument_name, date_time_array, rc);
py.getDateArray(argument_name, date_array, rc);
py.getTimeArray(argument_name, time_array, rc);
Array output argument
setters:
rc = py.setOutStringArray(argument_name);
rc = py.setOutBoolArray(argument_name);
rc = py.setOutLongArray(argument_name);
rc = py.setOutIntArray(argument_name);
rc = py.setOutDoubleArray(argument_name);
rc = py.setOutDateTimeArray(argument_name);
rc = py.setOutDateArray(argument_name);
rc = py.setOutTimeArray(argument_name);
Python 2.x uses
ASCII as the default encoding. Therefore, you must specify another
encoding at the top of the file to use non-ASCII Unicode characters
in literals. As a best practice, when using Python 2.x,
always use the following as the first line of your Python script:
Also, in Python 2.x,
the Unicode literal must be preceded by the letter u. Therefore,
literal strings should be written using the following form:
Note: Python 3.x uses
UTF-8 as the default encoding, so these issues affect Python 2.x only.
When using Python 3.x, the
default encoding can be used, and literals can simply be enclosed
in quotation marks.