How do I use loadSlice in Ice for Python?

Ice for Python supports two types of code generation: static and dynamic. Static code generation, which will be familiar to users of compiled languages such as C++ and Java, uses the Slice compiler slice2py to create Python source files from Slice definitions at compile time. On the other hand, when a program calls the Ice.loadSlice function, code is generated from Slice definitions dynamically at run time. Dynamic code generation slightly increases program start-up time but eliminates the need to generate and manage additional Python source files.

Users of dynamic code generation sometimes encounter problems when multiple Slice files are involved. For example, consider the following Slice definitions:

Slice
// A.ice
module A
{
    struct Pair 
    {
        long first;
        long second; 
    }
}
                 
// B.ice
#include <A.ice>
module B
{
    interface Mapper
    {
        void doit(A::Pair p);
    }
}

Now run python as follows:

Python
$ python 
>>> import Ice
>>> Ice.loadSlice("B.ice")
B.ice:1: error: Can't open include file "B.ice"
    #include <B.ice>
1 error in preprocessor.
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
RuntimeError: Slice preprocessing failed for `B.ice'

The problem in this case is that B.ice includes A.ice but the compiler cannot find A.ice because the include path is not set. To remedy this, use the -I option to tell the code generator where to find the included files. Assuming A.ice resides in the same directory as B.ice, you can use the following command:

Python
>>> Ice.loadSlice('-I. B.ice')
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "B.ice", line 3, in ?
    module A
ImportError: No module named A_ice

Now A.ice is found, but loadSlice complains about an import error. As explained in the manual, the reason for this error is that, by default, the code generator creates Python code only for the Slice definitions in the specified file; for included files, it instead generates equivalent Python import statements. In other words, by default, the compiler assumes that included files have already been translated statically. (The reason for this behavior is that it allows you to combine dynamic and static code generation when necessary.)

To get the compiler to generate code for both B.ice and the included A.ice file, we need to specify the --all option:

>>> Ice.loadSlice('-I. --all B.ice')

This recursively translates B.ice and all files included by B.ice.

See Also