Here in this post we will see how to convert a python application into a standalone windows executable. So that, windows users can run them without installing windows binaries of python and its related libraries separately.
In this we will write a small python code which uses the pubsub and pygtk libraries. And we shall see, how to write the setup script for it using py2exe and cx_Freeze in order to produce a standalone windows application.
Introduction
The job of a packaging/distribution tool is to build a list of dependent modules that are needed for the python application and include those modules for packaging. The list of dependent modules are specified via packaging options provided in the conventional setup.py file and/or by recursively finding the modules from the
There are certain limitations when a packaging tool tries to find the dependent modules from the import statements. If the python code imports modules using the
Python pubsub package
The pubsub module supports two different messaging protocols namely args1 and kwargs. Choosing and switching between these protocols are done by modifying the module path dynamically. This can result in import error like this during runtime.
This is the main reason I choose pubsub for my example. In the following sections we shall see how to package them successfully for windows.
Sample code
Lets consider a sample application consisting of a single file named say testpubsub.py with the following code
In the above application, the listener displays the message received from the sender using gtk's message dialog popup. Now, we shall see, how to write the conventional setup.py file for it, using py2exe and cx_Freeze.
Setup file using py2exe
The setup.py using py2exe would look something like this
Here we can see the
As the final package has the entire pubsub module, the windows executable will have no trouble in finding the dynamic protocol libraries during runtime.
To generate exe file, run the following in the build machine (i.e. a windows machine with python and necessary library dependencies installed)
this will produce a standalone windows executable file named testpubsub.exe
Setup file using cx_Freeze
The setup.py using cx_Freeze would look something like this
The
Run the following in the build machine to generate the exe file
We can safely ignore the missing modules warning in the build log
The above listed missing modules are under
Voila! We have created a standalone windows application from a python script. :)
In this we will write a small python code which uses the pubsub and pygtk libraries. And we shall see, how to write the setup script for it using py2exe and cx_Freeze in order to produce a standalone windows application.
Introduction
The job of a packaging/distribution tool is to build a list of dependent modules that are needed for the python application and include those modules for packaging. The list of dependent modules are specified via packaging options provided in the conventional setup.py file and/or by recursively finding the modules from the
import
statements used in the code.There are certain limitations when a packaging tool tries to find the dependent modules from the import statements. If the python code imports modules using the
__import__
statement or if the python code modifies the sys.path
at runtime in order to import certain modules, then those modules will not be found successfully by the packaging tool.Python pubsub package
The pubsub module supports two different messaging protocols namely args1 and kwargs. Choosing and switching between these protocols are done by modifying the module path dynamically. This can result in import error like this during runtime.
from listenerimpl import Listener, ListenerValidator
ImportError: No module named listenerimpl
This is the main reason I choose pubsub for my example. In the following sections we shall see how to package them successfully for windows.
Sample code
Lets consider a sample application consisting of a single file named say testpubsub.py with the following code
from pubsub import pub
import gtk
def listener1(msg):
ms = gtk.MessageDialog(None, 0, gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE,
"The listener received the message : %s" % (msg, ))
ms.run()
ms.destroy()
pub.subscribe(listener1, 'test.pubsub')
def sender():
pub.sendMessage('test.pubsub', msg="Hola! this is a test message")
if __name__ == "__main__":
sender()
In the above application, the listener displays the message received from the sender using gtk's message dialog popup. Now, we shall see, how to write the conventional setup.py file for it, using py2exe and cx_Freeze.
Setup file using py2exe
The setup.py using py2exe would look something like this
from distutils.core import setup
try:
import py2exe
except:
pass
setup (
name='TestPubSub',
description="Script to test pubsub for packaging",
version="0.1",
windows=[{'script': 'testpubsub.py'}],
platforms=["any"],
options={ 'py2exe': {
'packages': 'encodings, pubsub',
'includes': 'cairo, pango, pangocairo, atk, gobject, gio'}
},
)
Here we can see the
packages
option specified for py2exe, to include the encodings
and pubsub
packages explicitly. This will include the entire pubsub (and encodings) modules from the installation location for packaging.As the final package has the entire pubsub module, the windows executable will have no trouble in finding the dynamic protocol libraries during runtime.
To generate exe file, run the following in the build machine (i.e. a windows machine with python and necessary library dependencies installed)
$ python setup.py py2exe
this will produce a standalone windows executable file named testpubsub.exe
Setup file using cx_Freeze
The setup.py using cx_Freeze would look something like this
from cx_Freeze import setup, Executable
import platform
if platform.system() == 'Windows':
bse = 'Win32GUI'
else:
bse = None
opts = { 'compressed' : True,
'create_shared_zip' : False,
'packages' : ['pubsub.core.kwargs', 'pubsub.core.arg1'],
}
WIN_Target = Executable(
script='testpubsub.py',
base=bse,
targetName='testpubsub.exe',
compress=True,
appendScriptToLibrary=False,
appendScriptToExe=True
)
setup(
name='TestPubSub',
description="Script to test pubsub for packaging",
version='0.1',
options={'build_exe' : opts},
executables=[WIN_Target]
)
The
packages
option slightly differs for cx_Freeze. Here we have to explicitly include the sub packages of pubsub library namely, pubsub.core.kwargs
and pubsub.core.arg1
so that, all the modules under them gets included for packaging.Run the following in the build machine to generate the exe file
$ python setup.py build
We can safely ignore the missing modules warning in the build log
Missing modules:
? core.publisher imported from pubsub.pub
? listenerimpl imported from pubsub.core.listener
? publishermixin imported from pubsub.core.topicobj
? topicargspecimpl imported from pubsub.core.topicargspec
? topicmgrimpl imported from pubsub.core.topicmgr
The above listed missing modules are under
pubsub.core.kwargs
and pubsub.core.arg1
. In cx_Freeze, the list of dependent modules are gathered from the import
statements used in the code. While constructing this list, cx_Freeze reports missing modules, when a particular module has been imported in the code but not found in sys.path
. But, as we have included those modules directly via the packages
option, these modules will get safely included in the package. So, there won't be any runtime error.Voila! We have created a standalone windows application from a python script. :)