Monday, August 14, 2006

Deploying the GDATA Reader as an executable

Now that we have a working GDATA reader, it would be nice to make it into a CLI executable. IronPython provides a couple of ways to do this. The IronPython console application ipy.exe has an extension switch called SaveAssemblies. This will save the main Python script and any imported Python file as separate executables of the same basename. This is good if you have a simple single Python program that isn't dependent of other Python modules. Running the following command will create a gdatareader.exe in the same directory as the Python program.
ipy.exe -X:SaveAssemblies gdatareader.py
It has a limitation that it will display a console window as well as the application when you run it. Also the IronPython team do not recommend it as the best way to create an executable. They recommend using the IronPython.Hosting.PythonCompiler class. I have created a simple Python script makeexe.py that uses this class to compile one or more Python files into a CLI executable. The executable is created as a true Windows application so there is no console. For both these methods, the created executable requires the gdata.dll, IronPython.dll and IronMath.dll assemblies in the same directory or in the GAC.

import sys
from IronPython.Hosting import PythonCompiler
from System.Reflection.Emit import PEFileKinds

from System.Collections.Generic import List
sources = List[str]()

for file in sys.argv[1:-1]:
sources.Add(file)
exename = sys.argv[-1]

compiler = PythonCompiler(sources, exename)
compiler.MainFile = sys.argv[1]
compiler.TargetKind = PEFileKinds.WindowApplication
compiler.IncludeDebugInformation = False
compiler.Compile()

You just need to provide the list of Python files and the name of the executable to be generated.

ipy.exe makeexe.py gdatareader.py gdatareader.exe

If you provide more than one Python file, the first file must contain the main logic. If the main logic is activated as follows:

if __name__ == "__main__":

this will need to be modified as the __name__ variable is set to the name of the executable without the .exe extension. The following works for me:

if __name __ == "__main__" or __name__ == sys.executable:

Modified versions of the GDATA reader scripts from the previous post are available. gdatareader.py gdatareaderrtf.py

2 comments:

Anonymous said...

I try this on Linux/Mono(1.1.16.1) and IP RC1 and it works. But executable need IronPython.dll and IronMath.dll (in GAC or in current directory). Is this regular behavior?

hexdump42 said...

Yes, you still need to have the IronPython.dll and IronMath.dll in the current directory or the GAC. The best thing about the second method is any imported python modules are included as part of the executable.