Initializing help system before first use

I/O drivers

The python3 module provides a driver that is designed to be used in initializations blocks for both reading data from and writing data to Python.

Driver python

python:module_name

The driver can only be used in `initializations' blocks. The string after the colon is the Python module name to read the data from or write the data to. Using the predefined constant PY_IO_GLOBAL_VAR = "python:__main__" as file name will initialize the Mosel variables from and to global Python variables. Alternatively, you can create your own modules by initializing data to, for example, "python:client_data". To access your own modules in Python, you need to import them like a normal Python module ("import client_data"). After importing the module, the imported Mosel variables will be the attributes of the module, for example, client_data.names.

When initializing data from Mosel to Python, a possibly existing Python objects with the same name will be replaced by a new Python object with a Python object type that matches the one of the Mosel source variable.

When initializing arrays, sets, or lists from Python to Mosel, the initialization behavior is additive: The elements of the Python structures are added to the Mosel structures and existing elements in the Mosel structures will not be deleted automatically. If, for example, the target Mosel array is dense and the source Python dictionary is sparse, then the Mosel array may contain old and new values after initialization from Python. If the Mosel array is meant to contain only the values retrieved from the Python dictionary, it is recommended to define it as dynamic and to delete the non-zero elements with delcell(dynamic_array) before initializing it from Python.

The optional label entries in an initialization block are understood as Python variable (or module attribute) names.

Type mapping to Python:

  • Mosel boolean → Python bool
  • Mosel integer → Python int
  • Mosel real → Python float
  • Mosel string → Python str
  • Mosel set → Python set
  • Mosel list → Python list
  • Mosel array(I) → Python dictionary with scalar keys
  • Mosel array(I, J, ...) → Python dictionary with tuples of scalars as keys
  • Mosel nested types → Python nested type
  • Mosel records: not supported
  • Mosel external types: not supported
Type mapping from Python:
  • Mosel boolean ← Python bool
  • Mosel int ← Python int
  • Mosel real ← Python int, Python float
  • Mosel string ← String representation of Python object as returned by repr()
  • Mosel list ← Python list
  • Mosel set ← iterable types (e.g., set, generator, generator expression, classes that implement __iter__())
  • Mosel array ← dictionary with scalar or tuple keys
  • Mosel nested types ← Python nested type of supported subtypes
  • Mosel records: not supported
  • Mosel external types: not supported

In the following example, a sparse array is transferred to Python and then the same array is reused for retrieving data from a sparse Python dictionary.

model "Python I/O example"
  uses "python3"

  declarations
    I = 1..4
    A: dynamic array(I) of integer
  end-declarations

  A(1) := 1*2; A(3) := 3*2

  initializations to PY_IO_GLOBAL_VAR
    I as "MyRange"
    A
  end-initializations

  pyrun("io-example.py")
  delcell(A) ! Delete existing elements from array A.

  initializations from PY_IO_GLOBAL_VAR
    A
  end-initializations

  writeln("Values initialized from Python:")
  writeln("  A   = ", A)
end-model

The content of io-example.py:

print("Values initialized to Python:")
print("  MyRange =", MyRange)
print("  A =", A)
print("Modifying data in Python...")
A = {i: 2 * i for i in MyRange if i % 2 == 0}

Executing this model generates the following output:

Values initialized to Python:
  MyRange = range(1, 5)
  A = {1: 2, 3: 6}
Modifying data in Python...
Values initialized from Python:
  A   = [(2,4),(4,8)]