This document describes how to use Freeze for the Win32 platform.
Freeze itself is a Python tool for creating stand-alone executables from Python source code. This document does not attempt to document freeze itself - only the win32 specific changes.
Frozen programs under Win32 can (theoretically) freeze any type of program supported by Python on Win32 - At the moment, Console .EXE and NT Service .EXE programs are supported. GUI Python programs and COM .EXE programs are very nearly all ready to go.
The person freezing the program has control over what external DLLs are required by a frozen program. The following dependencies are supported:
These programs freeze only .py files in your program. All external DLLs are required at run-time. This includes all .pyd/.dll modules used by your program, Python20.dll, and msvcrt.dll.
A small Python program would typically create a .EXE around 300kb.
Note: For Python1.5.1, you must get a patch from Guido to import.c for this to work.
These programs also freeze in the sources from all .pyd and .dll files used at runtime. This means the resulting .EXE is only dependent on Python20.dll and msvcrt.dll.
A small Python program using win32api, win32con and one or 2 other win32 extensions would typically create a .EXE around 400kb.
Completely stand-alone programs, as is the default on Unix systems. These are currently not supported, mainly as the size of a decent Python program gets very large. However, by tweaking the existing Unix support, this would not be difficult to do.
By default, a file in the main "freeze" directory called "extensions_win32.ini" is used to obtain information about frozen extensions. A typical entry is:
[win32api]
dsp=%PYTHONEX%\win32\win32api.dsp
cl=/I %PYTHONEX%\win32\src
libs=kernel32.lib user32.lib shell32.lib advapi32.lib
This entry indicates that the win32api extension module is defined in the MSVC project file "%PYTHONEX%\win32\win32api.dsp
". Note the use of
"%PYTHONEX%"
- most strings are substituted with environment variables. In this case, it is assumed variable PYTHONEX points to the main "Python Extensions" source directory (which is assumed to be in the same structure as the release of the extension sources).
An entry in a .INI file can also control specific compiler options, and also the .lib files necessary to be linked with the application.
To prevent freezing extension modules, simply exclude that module using the freeze "-x" switch.
Occasionally, it will be necessary to explicitly include dependent modules. For example, many win32 modules are dependent on the "pywintypes" module - for example, the win32api module. In this case, the module may be explicitly included using the freeze "-m" option.
PythonCOM.dll can be frozen as long as you are not implementing COM Servers. Ie, you can freeze programs which control other applications, but can not implement programs that are themselves controlled by other applications.
If you use any of the win32com .pyd extensions (ex, axscript, mapi, internet, axcontrol), then you will need to specify an additional "-a" option to point to the win32comext directory. There is an example below.
The use of the "win32com.client.gencache" module is not supported (although could be quite easily??)
Before we start, we must:
D:\temp\delme>set PYTHONEX=d:\src\pythonex
import sys
print " ".join( ["Hello", "world"] + sys.argv[1:] )
\src\python-1.5.1\tools\freeze\freeze.py helloworld.py
nmake
Resulting helloworld.exe: 114,688 bytes.
Uses win32api. Demonstrates requirement for pywintypes, and difference between freezing extensions and not.
import win32api
print "Hello from", win32api.GetComputerName()
By default, win32api will be frozen in with the .EXE. If you do not provide the "pywintypes" inclusion, then the link step will fail looking for all the pywintypes modules.
\src\python-1.5.1\tools\freeze\freeze.py helloworld2.py -m pywintypes
nmake
Resulting helloworld2.exe: 167,936 bytes
Simply adding win32con to the mix gives an EXE of size: 352,768 bytes.
Using this build, we are dependent at runtime on the win32api.pyd and pywintypes15.dll files.
\src\python-1.5.1\tools\freeze\freeze.py -x win32api helloworld.py
Resulting helloworld2.exe: 114,688
Adding win32con to this build results in a size of: 252,928
Uses MAPI, a PythonCOM extension, and win32api.
from win32com.mapi import mapi
import win32api
mapi.MAPIInitialize( (mapi.MAPI_INIT_VERSION, 0) )
print "Hello from", win32api.GetComputerName()
mapi.MAPIUninitialize()
As it does not import pythoncom or pywintypes itself, they must be specified. As it uses the win32comext directory, -a must be used. If you have built the win32com extensions from sources, then the second -a is required.
\src\python-1.5.1\tools\freeze\freeze.py -a win32com=%PYTHONEX%\com\win32comext -a win32com.mapi=%PYTHONEX%\com\build\release testmapi.py -m pywintypes -m pythoncom
Resulting testmapi.exe: 352,768 bytes
This is a standard Python demo in the Win32 extensions. It can be found in the "win32\demos\service" directory.
This will create a native NT Service EXE, dependent only on the main Python20.dll. All other modules are built-in to the final .EXE
\src\python-1.5.1\tools\freeze\freeze.py -s service %PYTHONEX%\win32\demos\service\pipeTestService.py
Resulting pipeTestService.exe: 533,504 bytes.