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:
// 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 >>> 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:
>>> 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
.