Freeze for Win32

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

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.

Program Dependencies

The person freezing the program has control over what external DLLs are required by a frozen program. The following dependencies are supported:

Minimal frozen programs

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.

Frozen Extension programs

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 frozen programs

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.

Freezing Extension Modules

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.

Freezing Extension Module Considerations

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.

Freezing win32com and PythonCOM

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??)

Examples

Before we start, we must:

D:\temp\delme>set PYTHONEX=d:\src\pythonex

Helloworld.py

Source Code

import sys

 

print " ".join( ["Hello", "world"] + sys.argv[1:] )

Command Line used

\src\python-1.5.1\tools\freeze\freeze.py helloworld.py

nmake

Resulting helloworld.exe: 114,688 bytes.

Helloworld2.py

Uses win32api. Demonstrates requirement for pywintypes, and difference between freezing extensions and not.

Source Code

import win32api

print "Hello from", win32api.GetComputerName()

Command Line used

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.

Command Line used

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

Testmapi.py

Uses MAPI, a PythonCOM extension, and win32api.

Source Code

from win32com.mapi import mapi

import win32api

mapi.MAPIInitialize( (mapi.MAPI_INIT_VERSION, 0) )

print "Hello from", win32api.GetComputerName()

mapi.MAPIUninitialize()

Command Line used

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

PipeTestService.py

This is a standard Python demo in the Win32 extensions. It can be found in the "win32\demos\service" directory.

Command Line used

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.