Skip to main content

Freezes Python scripts into Windows apps

Project description

Freezes Python 3.6+ code into a Windows executable.

There are other projects that do this, but none were an exact fit for something simple.

  • Has a simple API that can be used outside of distutils / setuptools.

  • Python 3.6 support

  • Unlike some maintainers, I actually have Windows

Installing

Kelvin contains two executables which are built from C++ source, so use a binary wheel when possible:

pip install kelvin

If you want to build it yourself, install Visual Studio Build Tools 2017.

Note: Be sure to choose the Windows 8 SDK in the installer, not the Windows 10 SDK. The Windows 10 SDK does not include rc.exe (or it is not in the path), so the linking will fail with:

LINK : fatal error LNK1158: cannot run 'rc.exe'

Using

Import the kelvin Builder class and pass the appropriate options to its constructor. Then call build():

from kelvin.builder import Builder

b = Builder(script='src\\prog.py', dist='dist')
b.build()

This example creates the executable dist\prog.exe by analyzing the source for prog.py.

Options

Below are the Builder constructor parameters. Only script, dist, and version are required.

script

The initial script to start analyzing. Kelvin will start from this to find dependencies.

dist

The distribution directory where the executable will be constructed. If the directory exists, all content will be deleted without confirmation! Make sure this is correct. If it doesn’t exist, it will be created.

version

A string that determines the file version like “1.2.3.4”. Since this is put into the executable’s version resource, it can only contain numbers and periods. It cannot contain things like “-rc1”. This is a Windows limitation.

Windows versions always have 4 parts. If you specify fewer, “.0” will be appended for each missing part.

version_strings

Strings that are also included in the version resource and show up on the “Details” tab of the executable’s property sheet. These are provided a dictionary mapping a language id, such as 0x0409 for U.S. English, to another dictionary mapping from key to value:

version_strings = {
    0x0409: {
        'ProductName': 'product',
        'ProductVersion' : '1.2',
        'FileVersion': '1.2.3',
        'FileDescription': 'Descriptiion'
    }
}

Note: The FileVersion entry is a string, but it must only contain 1-4 numbers. If you put other things there, it causes the version information to be silently ignored.

filename

Normally the executable filename is the same as the script parameter, but a different filename can be supplied here. This should not contain a path - the resulting executable will be put into the dist directory.

subsystem

Can be ‘console’ (the default) or ‘windows’. This determines whether the final executable is a console application (also used for Windows services) or a GUI application.

path

Directories that dependencies can be found in, such as library directories. Kelvin will automatically search directories already in sys.path, so I recommend using virtual environments to ensure you don’t include global items.

include

A sequence of module names to include, used when modules cannot be identified automatically. They can be Python modules or extension modules.

exclude

Modules to exclude, used when modules are referenced in code but are known to not be needed. Kelvin has a large list of exclusions (in analyze.py) for items that are not needed on Windows, such as posixpath. (At this time there is no way to disable the default excludes.)

package_paths

If you have namespace packages that are split across multiple directories, you’ll need to pass them here. Kelvin does not actually run your code, so utilities like pkgutils.extend_path won’t take effect.

Provide a dictionary mapping from package name to a sequence of directories:

package_paths={'mylib': ('lib\\mylib1', 'lib\\mylib2')}
extra

A sequence of non-code files to be put into the executable. Each entry can be a relative filename, which will be copied into the executable with the same relative name, or a tuple pair containing the source path and the path to use in the archive:

extra = [
    'data\\schema.json',
    ('..\\docs\\README.rst', 'data\\README.rst)
]

This would include the put both files in the executable in a data directory.

To retrieve these files at runtime, open the executable (sys.executable) as a zip file using the zipfile package.

logger

A logging.Logger instance for Kelvin to output to. If not provided, a logger named “kelvin” is used.

Kelvin outputs very little at the INFO level. It outputs more at the DEBUG level which may be useful for troubleshooting. It also very detailed information at level 1, though this is most likely of interest for Kelvin development. (There is no constant like “TRACE” for this, so use logger.setLevel(1).)

report

Set to True to have ModuleFinder’s report printed to the console. This can be useful for debugging.

How It Works

Python’s built-in ModuleFinder class is used to analyze your source to find all modules it uses.

A precompiled executable is copied into the distribution directory. All needed Python modules are compiled into a zip file which is appended to the executable. On startup, the executable puts itself into sys.path and Python will load modules from it normally like any other zip file. (Interestingly, zip files are processed starting from the end, so we have a zip file with “garbage” (the executable) at the beginning which is ignored.)

Extension modules are actually DLLs, so they are copied, along with any dependencies, into the distribution directory, which is also added to sys.path.

This project used to support Python 2.7+, but I am now only supporting Python 3.6+ since it no longer requires messing with Windows manifest files. (It is possible that change was made in Python in 3.5.) If you need a manifest file, you can either add it after the executable is complete or you can put it in the same directory as the executable.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kelvin-2.0.1.tar.gz (16.3 kB view hashes)

Uploaded Source

Built Distribution

kelvin-2.0.1-py3-none-any.whl (33.2 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page