Macro Environment

The sardana server provides a global space to store variables, called Macro Environment. It is a store of variable - value pairs, which can be accessed during macro execution at any time. One of its common use case is to share configuration (or even small data) between different macros.

The macro environment is stored persistently, so if the sardana server is restarted the environment is properly restored.

The most common way of accessing environment variables is using environment related macros:

LAB-01-D01 [1]: senv Foo Bar
Foo = Bar

LAB-01-D01 [1]: genv Foo
Foo =
'Bar'

Important

Environment variable names are case sensitive. So, variable Foo is a different variable than foo.

Sardana built-in macros use a set of standard environment variables listed in Environment Variable Catalog. You can also define your own environment variables.

Environment Variables Types

Environment variables can be of different Python literal types: string, numbers, collections, etc. The type interpreation is based on Python’s ast.literal_eval() function. So, all the values not evaluating into Python literal structures are interpreted as strings.

For example, you can define a dictionary value in the following way:

LAB-01-D01 [1]: senv Foo '{"Bar": "Baz"}'
Foo = {'Bar': 'Baz'}

Environment Variables Scope

An environment variable can be set on different scope:

  • global (default)

  • door

  • macro

In order to set a variable for a specific scope you must preceed its name with the scope name separated by . (dot(s)).

For example to define a variable on a specific Door scope:

LAB-01-D01 [1]: senv LAB/01/D02.Foo Bar
LAB/01/D02.Foo = Bar

This way the Foo variable will be known only to the macros running on LAB/01/D02 door and will override the Foo variable defined on the global scope.

Important

Remember to use Door device name for defining variables on the door scope. Currently you can not use the Door alias.

Furthermore, the door and the macro scope can be mixed together, so an environment variable could only apply to a specific macro executed on a specific door.

For example to define a variable that apply only to the foo macro when run on a specific door:

LAB-01-D01 [1]: senv LAB/01/D02.foo.Bar Baz
LAB/01/D02.foo.Bar = Baz

Environment variables at the macro scope are inherited, meaning that variables defined in parent macros take precedence over those defined at the global scope.

For example, consider the following two macros:

@macro()
def foo(self):
    xyz = self.getEnv('xyz')
    self.output(f"xyz (from foo) = {xyz}")
    self.runMacro("bar")

@macro()
def bar(self):
    xyz = self.getEnv('xyz')
    self.output(f"xyz (from bar) = {xyz}")

If we define both macro and global scope variables with the same name and then call the macros, we can see that the parent macro variable is used by the child macro instead of the global one:

Door_1 [1]: senv foo.xyz 1
xyz = 1

Door_1 [2]: senv xyz 2
xyz = 2

Door_1 [3]: foo
xyz (from foo) = 1
xyz (from bar) = 1

Door_1 [4]: bar
xyz (from bar) = 2

See also

Apart of the environment related macros you have other API for accessing environment.

Macro API reference

the Macro API

Taurus Extensions

the Taurus Extension API to MacroServer and Door Tango devices

Door

the Door Tango device API

MacroServer

the MacroServer Tango device API