PyInstaller Manual¶
- Version
PyInstaller 4.9
- Homepage
- Contact
- Authors
David Cortesi, based on structure by Giovanni Bajo & William Caban, based on Gordon McMillan’s manual
- Copyright
This document has been placed in the public domain.
PyInstaller bundles a Python application and all its dependencies into a single package. The user can run the packaged app without installing a Python interpreter or any modules. PyInstaller supports Python 3.6 or newer, and correctly bundles the major Python packages such as numpy, PyQt, Django, wxPython, and others.
PyInstaller is tested against Windows, Mac OS X, and GNU/Linux. However, it is not a cross-compiler: to make a Windows app you run PyInstaller in Windows; to make a GNU/Linux app you run it in GNU/Linux, etc. PyInstaller has been used successfully with AIX, Solaris, FreeBSD and OpenBSD but testing against them is not part of our continuous integration tests.
What’s New This Release¶
Release 4.0 adds support for 3rd-party packages to provide PyInstaller hooks along with the package. This allows Maintainers of other Python packages to deliver up-to-date PyInstaller hooks as part of their package. See our sample project for more information.
PyInstaller uses this option itself to provide updated hooks much faster: Many hooks are moved into the new package pyinstaller-hooks-contrib, which is updated monthly. This package is installed automatically when installing PyInstaller, but can also be updated independently.
Finally, this version drops support for Python 2.7, which is end-of-life since January 2020.. The minimum required version is now Python 3.6. The last version supporting Python 2.7 was PyInstaller 3.6.
Contents:
Requirements¶
Windows¶
PyInstaller runs in Windows 8 or newer (Windows 7 should work too, but is not supported). It can create graphical windowed apps (apps that do not need a command window).
PyInstaller requires two Python modules in a Windows system. It requires either the PyWin32 or pypiwin32 Python extension for Windows. If you install PyInstaller using pip, and PyWin32 is not already installed, pypiwin32 is automatically installed. PyInstaller also requires the pefile package.
The pip-Win package is recommended, but not required.
Mac OS X¶
PyInstaller runs in Mac OS X 10.7 (Lion) or newer. It can build graphical windowed apps (apps that do not use a terminal window). PyInstaller builds apps that are compatible with the Mac OS X release in which you run it, and following releases. It can build 32-bit binaries in Mac OS X releases that support them.
GNU/Linux¶
PyInstaller requires the ldd
terminal application to discover
the shared libraries required by each program or shared library.
It is typically found in the distribution-package glibc
or libc-bin
.
It also requires the objdump
terminal application to extract
information from object files
and the objcopy
terminal application to append data to the
bootloader.
These are typically found in the distribution-package binutils
.
AIX, Solaris, FreeBSD and OpenBSD¶
Users have reported success running PyInstaller on these platforms,
but it is not tested on them.
The ldd
and objdump
commands are needed.
Each bundled app contains a copy of a bootloader, a program that sets up the application and starts it (see The Bootstrap Process in Detail).
When you install PyInstaller using pip, the setup will attempt to build a bootloader for this platform. If that succeeds, the installation continues and PyInstaller is ready to use.
If the pip setup fails to build a bootloader, or if you do not use pip to install, you must compile a bootloader manually. The process is described under Building the Bootloader.
License¶
PyInstaller is distributed under the GPL License but with an exception that allows you to use it to build commercial products:
You may use PyInstaller to bundle commercial applications out of your source code.
The executable bundles generated by PyInstaller from your source code can be shipped with whatever license you want.
You may modify PyInstaller for your own needs but changes to the PyInstaller source code fall under the terms of the GPL license. That is, if you distribute your modifications you must distribute them under GPL terms.
For updated information or clarification see our FAQ at the PyInstaller home page.
How To Contribute¶
You are very welcome to contribute! PyInstaller is a maintained by a group of volunteers. All contributions, like community support, bug reports, bug fixes, documentation improvements, enhancements and ideas are welcome.
PyInstaller is an free software project that is created and maintained by volunteers. It lives-and-dies based on the support it receives from others, and the fact that you’re even considering contributing to PyInstaller is very generous of you.
Since as of now all core-developers are working on PyInstaller in their spare-time, you can help us (and the project) most if you are following some simple guidelines. The higher the quality of your contribution, the less work we have incorporating them and the earlier we will be able to incorporate them :-)
If you get stuck at any point you can ask on the PyInstaller Email List or create a ticket on GitHub.
For more about our development process and methods, see the Development Guide.
Some ideas how you can help¶
Some ideas how you can help:
Subscribe to the mailing list (low traffic) or join the IRC channel and share your experience or answer questions from the community.
Answer support tickets: Often the user just needs to be pointed to the fitting section in the manual.
Triage open issues, which means: read the report; ask the issue requester to provide missing information and to try with the latest development version; ensure there is a minimal example; ensure the issue-reporter followed all steps in When Things Go Wrong. If you are able reproduce the problem and track down the bug, this would be a great help for the core developers.
Help improving the documentation: There is a list of documentation issues you can pick one from. Please provide a pull-request for your changes. Read more »»
Pick an issue requesting a pull-request and provide one.
Review pull requests: Are the commit messages following the guideline Please Write Good Commit Messages; do all new files have a copyright-header (esp. for hooks this is often missing); is the code okay; etc.
Scan the list of open issues and pick some task :-)
Thank you very much!
If you plan to contribute frequently, just ask for write access to the main git repository. We would be glad to welcome you in the team!
Sponsorship and Project Grant¶
Please consider sponsoring PyInstaller development, especially if your company benefits from this project.
We welcome your patronage on Bountysource:
Contribute a recurring amount to the team
Place a bounty on a specific feature
Your contribution will go towards adding new features to PyInstaller and making sure all functionality continues to meet our high quality standards.
A grant for contiguous full-time development has the biggest impact for progress. Periods of 3 to 10 days allow a contributor to tackle substantial complex issues which are otherwise left to linger until somebody can’t afford to not fix them.
Contact Hartmut Goebel to arrange a grant for a core contributor.
Huge thanks to all the companies and individuals who financially contributed to the development of PyInstaller. Please send a PR if you’ve donated and would like to be listed on the web-site.
How to Install PyInstaller¶
PyInstaller is a normal Python package. You can download the archive from PyPi, but it is easier to install using pip where is is available, for example:
pip install pyinstaller
or upgrade to a newer version:
pip install --upgrade pyinstaller
To install the current development version use:
pip install https://github.com/pyinstaller/pyinstaller/tarball/develop
Installing in Windows¶
For Windows, PyWin32 or the more recent pypiwin32, is a prerequisite. The latter is installed automatically when you install PyInstaller using pip or easy_install. If necessary, follow the pypiwin32 link to install it manually.
It is particularly easy to use pip-Win to install PyInstaller along with the correct version of PyWin32. pip-Win also provides virtualenv, which makes it simple to maintain multiple different Python interpreters and install packages such as PyInstaller in each of them. (For more on the uses of virtualenv, see Supporting Multiple Platforms below.)
When pip-Win is working, enter this command in its Command field and click Run:
venv -c -i pyi-env-name
This creates a new virtual environment rooted at C:\Python\pyi-env-name
and makes it the current environment.
A new command shell
window opens in which you can run commands within this environment.
Enter the command
pip install PyInstaller
Once it is installed, to use PyInstaller,
Start pip-Win
In the Command field enter
venv pyi-env-name
Click Run
Then you have a command shell window in which commands such as pyinstaller execute in that Python environment.
Installing in Mac OS X¶
Mac OS X 10.8 comes with Python 2.7 pre-installed by Apple. However, Python 2.7 is end-of-life and no longer supported by PyInstaller, also major packages such as PyQt, Numpy, Matplotlib, Scipy, and the like, have dropped support for Python 2.7, too. Thus we strongly recommend that you install these using either MacPorts or Homebrew.
PyInstaller users report fewer problems when they use a package manager than when they attempt to install major packages individually.
Alternatively you might install Python 3 following the official guide.
Installing from the archive¶
If pip is not available, download the compressed archive from PyPI. If you are asked to test a problem using the latest development code, download the compressed archive from the develop branch of PyInstaller Downloads page.
Expand the archive.
Inside is a script named setup.py
.
Execute python setup.py install
with administrator privilege to install or upgrade PyInstaller.
For platforms other than Windows, GNU/Linux and Mac OS, you must first
build a bootloader program for your platform: see Building the Bootloader.
After the bootloader has been created,
use python setup.py install
with administrator privileges
to complete the installation.
Verifying the installation¶
On all platforms, the command pyinstaller
should now exist on the
execution path. To verify this, enter the command:
pyinstaller --version
The result should resemble 3.n
for a released version,
and 3.n.dev0-xxxxxx
for a development branch.
If the command is not found, make sure the execution path includes the proper directory:
Windows:
C:\PythonXY\Scripts
where XY stands for the major and minor Python version number, for exampleC:\Python34\Scripts
for Python 3.4)GNU/Linux:
/usr/bin/
OS X (using the default Apple-supplied Python)
/usr/bin
OS X (using Python installed by homebrew)
/usr/local/bin
OS X (using Python installed by macports)
/opt/local/bin
To display the current path in Windows the command is echo %path%
and in other systems, echo $PATH
.
Installed commands¶
The complete installation places these commands on the execution path:
pyinstaller
is the main command to build a bundled application. See Using PyInstaller.pyi-makespec
is used to create a spec file. See Using Spec Files.pyi-archive_viewer
is used to inspect a bundled application. See Inspecting Archives.pyi-bindepend
is used to display dependencies of an executable. See Inspecting Executables.pyi-grab_version
is used to extract a version resource from a Windows executable. See Capturing Windows Version Data.
If you do not perform a complete installation
(installing via pip
or executing setup.py
),
these commands will not be installed as commands.
However, you can still execute all the functions documented below
by running Python scripts found in the distribution folder.
The equivalent of the pyinstaller
command is
pyinstaller-folder/pyinstaller.py
.
The other commands are found in pyinstaller-folder/cliutils/
with meaningful names (makespec.py
, etc.)
What PyInstaller Does and How It Does It¶
This section covers the basic ideas of PyInstaller. These ideas apply to all platforms. Options and special cases are covered below, under Using PyInstaller.
PyInstaller reads a Python script written by you. It analyzes your code to discover every other module and library your script needs in order to execute. Then it collects copies of all those files – including the active Python interpreter! – and puts them with your script in a single folder, or optionally in a single executable file.
For the great majority of programs, this can be done with one short command,
pyinstaller myscript.py
or with a few added options, for example a windowed application as a single-file executable,
pyinstaller --onefile --windowed myscript.py
You distribute the bundle as a folder or file to other people, and they can execute your program. To your users, the app is self-contained. They do not need to install any particular version of Python or any modules. They do not need to have Python installed at all.
Note
The output of PyInstaller is specific to the active operating system and the active version of Python. This means that to prepare a distribution for:
a different OS
a different version of Python
a 32-bit or 64-bit OS
you run PyInstaller on that OS, under that version of Python. The Python interpreter that executes PyInstaller is part of the bundle, and it is specific to the OS and the word size.
Analysis: Finding the Files Your Program Needs¶
What other modules and libraries does your script need in order to run? (These are sometimes called its “dependencies”.)
To find out, PyInstaller finds all the import
statements
in your script.
It finds the imported modules and looks in them for import
statements, and so on recursively, until it has a complete list of
modules your script may use.
PyInstaller understands the “egg” distribution format often used for Python packages. If your script imports a module from an “egg”, PyInstaller adds the egg and its dependencies to the set of needed files.
PyInstaller also knows about many major Python packages, including the GUI packages Qt (imported via PyQt or PySide), WxPython, TkInter, Django, and other major packages. For a complete list, see Supported Packages.
Some Python scripts import modules in ways that PyInstaller cannot detect:
for example, by using the __import__()
function with variable data,
using importlib.import_module()
,
or manipulating the sys.path
value at run time.
If your script requires files that PyInstaller does not know about,
you must help it:
You can give additional files on the
pyinstaller
command line.You can give additional import paths on the command line.
You can edit the
myscript.spec
file that PyInstaller writes the first time you run it for your script. In the spec file you can tell PyInstaller about code modules that are unique to your script.You can write “hook” files that inform PyInstaller of hidden imports. If you create a “hook” for a package that other users might also use, you can contribute your hook file to PyInstaller.
If your program depends on access to certain data files, you can tell PyInstaller to include them in the bundle as well. You do this by modifying the spec file, an advanced topic that is covered under Using Spec Files.
In order to locate included files at run time, your program needs to be able to learn its path at run time in a way that works regardless of whether or not it is running from a bundle. This is covered under Run-time Information.
PyInstaller does not include libraries that should exist in
any installation of this OS.
For example in GNU/Linux, it does not bundle any file
from /lib
or /usr/lib
, assuming
these will be found in every system.
Bundling to One Folder¶
When you apply PyInstaller to myscript.py
the default
result is a single folder named myscript
.
This folder contains all your script’s dependencies,
and an executable file also named myscript
(myscript.exe
in Windows).
You compress the folder
to myscript.zip
and transmit it to your users.
They install the program simply by unzipping it.
A user runs your app by
opening the folder and launching the myscript
executable inside it.
It is easy to debug problems that occur when building the app when you use one-folder mode. You can see exactly what files PyInstaller collected into the folder.
Another advantage of a one-folder bundle
is that when you change your code, as long
as it imports exactly the same set of dependencies, you could send out
only the updated myscript
executable.
That is typically much smaller
than the entire folder.
(If you change the script so that it imports more
or different dependencies, or if the dependencies
are upgraded, you must redistribute the whole bundle.)
A small disadvantage of the one-folder format is that the one folder contains
a large number of files.
Your user must find the myscript
executable
in a long list of names or among a big array of icons.
Also your user can create
a problem by accidentally dragging files out of the folder.
How the One-Folder Program Works¶
A bundled program always starts execution in the PyInstaller bootloader.
This is the heart of the myscript
executable in the folder.
The PyInstaller bootloader is a binary
executable program for the active platform
(Windows, GNU/Linux, Mac OS X, etc.).
When the user launches your program, it is the bootloader that runs.
The bootloader creates a temporary Python environment
such that the Python interpreter will find all imported modules and
libraries in the myscript
folder.
The bootloader starts a copy of the Python interpreter to execute your script. Everything follows normally from there, provided that all the necessary support files were included.
(This is an overview. For more detail, see The Bootstrap Process in Detail below.)
Bundling to One File¶
PyInstaller can bundle your script and all its dependencies into a single
executable named myscript
(myscript.exe
in Windows).
The advantage is that your users get something they understand, a single executable to launch. A disadvantage is that any related files such as a README must be distributed separately. Also, the single executable is a little slower to start up than the one-folder bundle.
Before you attempt to bundle to one file, make sure your app works correctly when bundled to one folder. It is is much easier to diagnose problems in one-folder mode.
How the One-File Program Works¶
The bootloader is the heart of the one-file bundle also.
When started it creates a temporary folder
in the appropriate temp-folder location for this OS.
The folder is named _MEIxxxxxx
, where xxxxxx is a random number.
The one executable file contains an embedded archive of all the Python
modules used by your script, as well as
compressed copies of any non-Python support files (e.g. .so
files).
The bootloader uncompresses the support files and writes copies
into the the temporary folder.
This can take a little time.
That is why a one-file app is a little slower to start
than a one-folder app.
Note
PyInstaller currently does not preserve file attributes. see #3926.
After creating the temporary folder, the bootloader proceeds exactly as for the one-folder bundle, in the context of the temporary folder. When the bundled code terminates, the bootloader deletes the temporary folder.
(In GNU/Linux and related systems, it is possible
to mount the /tmp
folder with a “no-execution” option.
That option is not compatible with a PyInstaller
one-file bundle. It needs to execute code out of /tmp
.
If you know the target environment,
--runtime-tmpdir
might be a workaround.)
Because the program makes a temporary folder with a unique name, you can run multiple copies of the app; they won’t interfere with each other. However, running multiple copies is expensive in disk space because nothing is shared.
The _MEIxxxxxx
folder is not removed if the program crashes
or is killed (kill -9 on Unix, killed by the Task Manager on Windows,
“Force Quit” on Mac OS).
Thus if your app crashes frequently, your users will lose disk space to
multiple _MEIxxxxxx
temporary folders.
It is possible to control the location of the _MEIxxxxxx
folder by
using the --runtime-tmpdir
command line option. The specified path is
stored in the executable, and the bootloader will create the
_MEIxxxxxx
folder inside of the specified folder. Please see
Defining the Extraction Location for details.
Note
Do not give administrator privileges to a one-file executable (setuid root in Unix/Linux, or the “Run this program as an administrator” property in Windows 7). There is an unlikely but not impossible way in which a malicious attacker could corrupt one of the shared libraries in the temp folder while the bootloader is preparing it. Distribute a privileged program in one-folder mode instead.
Note
Applications that use os.setuid() may encounter permissions errors. The temporary folder where the bundled app runs may not being readable after setuid is called. If your script needs to call setuid, it may be better to use one-folder mode so as to have more control over the permissions on its files.
Using a Console Window¶
By default the bootloader creates a command-line console
(a terminal window in GNU/Linux and Mac OS, a command window in Windows).
It gives this window to the Python interpreter for its standard input and output.
Your script’s use of print
and input()
are directed here.
Error messages from Python and default logging output
also appear in the console window.
An option for Windows and Mac OS is to tell PyInstaller to not provide a console window. The bootloader starts Python with no target for standard output or input. Do this when your script has a graphical interface for user input and can properly report its own diagnostics.
As noted in the CPython tutorial Appendix,
for Windows a file extention of .pyw suppresses the console window
that normally appears.
Likewise, a console window will not be provided when using
a myscript.pyw
script with PyInstaller.
Hiding the Source Code¶
The bundled app does not include any source code.
However, PyInstaller bundles compiled Python scripts (.pyc
files).
These could in principle be decompiled to reveal the logic of
your code.
If you want to hide your source code more thoroughly, one possible option is to compile some of your modules with Cython. Using Cython you can convert Python modules into C and compile the C to machine language. PyInstaller can follow import statements that refer to Cython C object modules and bundle them.
Additionally, Python bytecode can be obfuscated with AES256 by specifying an encryption key on PyInstaller’s command line. Please note that it is still very easy to extract the key and get back the original bytecode, but it should prevent most forms of “casual” tampering. See Encrypting Python Bytecode for details.
Using PyInstaller¶
The syntax of the pyinstaller
command is:
pyinstaller
[options] script [script …] | specfile
In the most simple case,
set the current directory to the location of your program myscript.py
and execute:
pyinstaller myscript.py
PyInstaller analyzes myscript.py
and:
Writes
myscript.spec
in the same folder as the script.Creates a folder
build
in the same folder as the script if it does not exist.Writes some log files and working files in the
build
folder.Creates a folder
dist
in the same folder as the script if it does not exist.Writes the
myscript
executable folder in thedist
folder.
In the dist
folder you find the bundled app you distribute to your users.
Normally you name one script on the command line. If you name more, all are analyzed and included in the output. However, the first script named supplies the name for the spec file and for the executable folder or file. Its code is the first to execute at run-time.
For certain uses you may edit the contents of myscript.spec
(described under Using Spec Files).
After you do this, you name the spec file to PyInstaller instead of the script:
pyinstaller myscript.spec
The myscript.spec
file contains most of the information
provided by the options that were specified when
pyinstaller (or pyi-makespec)
was run with the script file as the argument.
You typically do not need to specify any options when running
pyinstaller with the spec file.
Only a few command-line options
have an effect when building from a spec file.
You may give a path to the script or spec file, for example
pyinstaller
options…~/myproject/source/myscript.py
or, on Windows,
pyinstaller "C:\Documents and Settings\project\myscript.spec"
Options¶
A full list of the pyinstaller
command’s options are as follows:
Positional Arguments¶
- scriptname¶
Name of scriptfiles to be processed or exactly one .spec file. If a .spec file is specified, most options are unnecessary and are ignored.
Optional Arguments¶
- -h, --help¶
show this help message and exit
- -v, --version¶
Show program version info and exit.
- --distpath DIR¶
Where to put the bundled app (default: ./dist)
- --workpath WORKPATH¶
Where to put all the temporary work files, .log, .pyz and etc. (default: ./build)
- -y, --noconfirm¶
Replace output directory (default: SPECPATH/dist/SPECNAME) without asking for confirmation
- --upx-dir UPX_DIR¶
Path to UPX utility (default: search the execution path)
- -a, --ascii¶
Do not include unicode encoding support (default: included if available)
- --clean¶
Clean PyInstaller cache and remove temporary files before building.
- --log-level LEVEL¶
Amount of detail in build-time console messages. LEVEL may be one of TRACE, DEBUG, INFO, WARN, ERROR, CRITICAL (default: INFO).
What To Generate¶
- -D, --onedir¶
Create a one-folder bundle containing an executable (default)
- -F, --onefile¶
Create a one-file bundled executable.
- --specpath DIR¶
Folder to store the generated spec file (default: current directory)
- -n NAME, --name NAME¶
Name to assign to the bundled app and spec file (default: first script’s basename)
What To Bundle, Where To Search¶
- --add-data <SRC;DEST or SRC:DEST>¶
Additional non-binary files or folders to be added to the executable. The path separator is platform specific,
os.pathsep
(which is;
on Windows and:
on most unix systems) is used. This option can be used multiple times.
- --add-binary <SRC;DEST or SRC:DEST>¶
Additional binary files to be added to the executable. See the
--add-data
option for more details. This option can be used multiple times.
- -p DIR, --paths DIR¶
A path to search for imports (like using PYTHONPATH). Multiple paths are allowed, separated by
':'
, or use this option multiple times. Equivalent to supplying thepathex
argument in the spec file.
Name an import not visible in the code of the script(s). This option can be used multiple times.
- --collect-submodules MODULENAME¶
Collect all submodules from the specified package or module. This option can be used multiple times.
- --collect-data MODULENAME, --collect-datas MODULENAME¶
Collect all data from the specified package or module. This option can be used multiple times.
- --collect-binaries MODULENAME¶
Collect all binaries from the specified package or module. This option can be used multiple times.
- --collect-all MODULENAME¶
Collect all submodules, data files, and binaries from the specified package or module. This option can be used multiple times.
- --copy-metadata PACKAGENAME¶
Copy metadata for the specified package. This option can be used multiple times.
- --recursive-copy-metadata PACKAGENAME¶
Copy metadata for the specified package and all its dependencies. This option can be used multiple times.
- --additional-hooks-dir HOOKSPATH¶
An additional path to search for hooks. This option can be used multiple times.
- --runtime-hook RUNTIME_HOOKS¶
Path to a custom runtime hook file. A runtime hook is code that is bundled with the executable and is executed before any other code or module to set up special features of the runtime environment. This option can be used multiple times.
- --exclude-module EXCLUDES¶
Optional module or package (the Python name, not the path name) that will be ignored (as though it was not found). This option can be used multiple times.
- --key KEY¶
The key used to encrypt Python bytecode.
- --splash IMAGE_FILE¶
(EXPERIMENTAL) Add an splash screen with the image IMAGE_FILE to the application. The splash screen can display progress updates while unpacking.
How To Generate¶
- -d {all,imports,bootloader,noarchive}, --debug {all,imports,bootloader,noarchive}¶
Provide assistance with debugging a frozen application. This argument may be provided multiple times to select several of the following options. - all: All three of the following options. - imports: specify the -v option to the underlying Python interpreter, causing it to print a message each time a module is initialized, showing the place (filename or built-in module) from which it is loaded. See https://docs.python.org/3/using/cmdline.html#id4. - bootloader: tell the bootloader to issue progress messages while initializing and starting the bundled app. Used to diagnose problems with missing imports. - noarchive: instead of storing all frozen Python source files as an archive inside the resulting executable, store them as files in the resulting output directory.
- --python-option PYTHON_OPTION¶
Specify a command-line option to pass to the Python interpreter at runtime. Currently supports “v” (equivalent to “–debug imports”), “u”, and “W <warning control>”.
- -s, --strip¶
Apply a symbol-table strip to the executable and shared libs (not recommended for Windows)
- --noupx¶
Do not use UPX even if it is available (works differently between Windows and *nix)
- --upx-exclude FILE¶
Prevent a binary from being compressed when using upx. This is typically used if upx corrupts certain binaries during compression. FILE is the filename of the binary without path. This option can be used multiple times.
Windows And Mac Os X Specific Options¶
- -c, --console, --nowindowed¶
Open a console window for standard i/o (default). On Windows this option has no effect if the first script is a ‘.pyw’ file.
- -w, --windowed, --noconsole¶
Windows and Mac OS X: do not provide a console window for standard i/o. On Mac OS this also triggers building a Mac OS .app bundle. On Windows this option is automatically set if the first script is a ‘.pyw’ file. This option is ignored on *NIX systems.
- -i <FILE.ico or FILE.exe,ID or FILE.icns or "NONE">, --icon <FILE.ico or FILE.exe,ID or FILE.icns or "NONE">¶
FILE.ico: apply the icon to a Windows executable. FILE.exe,ID: extract the icon with ID from an exe. FILE.icns: apply the icon to the .app bundle on Mac OS. Use “NONE” to not apply any icon, thereby making the OS to show some default (default: apply PyInstaller’s icon)
- --disable-windowed-traceback¶
Disable traceback dump of unhandled exception in windowed (noconsole) mode (Windows and macOS only), and instead display a message that this feature is disabled.
Windows Specific Options¶
- --version-file FILE¶
Add a version resource from FILE to the exe.
- -m <FILE or XML>, --manifest <FILE or XML>¶
Add manifest FILE or XML to the exe.
- --no-embed-manifest¶
Generate an external .exe.manifest file instead of embedding the manifest into the exe. Applicable only to onedir mode; in onefile mode, the manifest is always embedded, regardless of this option.
- -r RESOURCE, --resource RESOURCE¶
Add or update a resource to a Windows executable. The RESOURCE is one to four items, FILE[,TYPE[,NAME[,LANGUAGE]]]. FILE can be a data file or an exe/dll. For data files, at least TYPE and NAME must be specified. LANGUAGE defaults to 0 or may be specified as wildcard * to update all resources of the given TYPE and NAME. For exe/dll files, all resources from FILE will be added/updated to the final executable if TYPE, NAME and LANGUAGE are omitted or specified as wildcard *. This option can be used multiple times.
- --uac-admin¶
Using this option creates a Manifest that will request elevation upon application start.
- --uac-uiaccess¶
Using this option allows an elevated application to work with Remote Desktop.
Windows Side-By-Side Assembly Searching Options (Advanced)¶
- --win-private-assemblies¶
Any Shared Assemblies bundled into the application will be changed into Private Assemblies. This means the exact versions of these assemblies will always be used, and any newer versions installed on user machines at the system level will be ignored.
- --win-no-prefer-redirects¶
While searching for Shared or Private Assemblies to bundle into the application, PyInstaller will prefer not to follow policies that redirect to newer versions, and will try to bundle the exact versions of the assembly.
Mac Os Specific Options¶
- --osx-bundle-identifier BUNDLE_IDENTIFIER¶
Mac OS .app bundle identifier is used as the default unique program name for code signing purposes. The usual form is a hierarchical name in reverse DNS notation. For example: com.mycompany.department.appname (default: first script’s basename)
- --target-architecture ARCH, --target-arch ARCH¶
Target architecture (macOS only; valid values: x86_64, arm64, universal2). Enables switching between universal2 and single-arch version of frozen application (provided python installation supports the target architecture). If not target architecture is not specified, the current running architecture is targeted.
- --codesign-identity IDENTITY¶
Code signing identity (macOS only). Use the provided identity to sign collected binaries and generated executable. If signing identity is not provided, ad- hoc signing is performed instead.
- --osx-entitlements-file FILENAME¶
Entitlements file to use when code-signing the collected binaries (macOS only).
Rarely Used Special Options¶
- --runtime-tmpdir PATH¶
Where to extract libraries and support files in onefile-mode. If this option is given, the bootloader will ignore any temp-folder location defined by the run-time OS. The
_MEIxxxxxx
-folder will be created here. Please use this option only if you know what you are doing.
- --bootloader-ignore-signals¶
Tell the bootloader to ignore signals rather than forwarding them to the child process. Useful in situations where for example a supervisor process signals both the bootloader and the child (e.g., via a process group) to avoid signalling the child twice.
Shortening the Command¶
Because of its numerous options, a full pyinstaller
command
can become very long.
You will run the same command again and again as you develop
your script.
You can put the command in a shell script or batch file,
using line continuations to make it readable.
For example, in GNU/Linux:
pyinstaller --noconfirm --log-level=WARN \
--onefile --nowindow \
--add-data="README:." \
--add-data="image1.png:img" \
--add-binary="libfoo.so:lib" \
--hidden-import=secret1 \
--hidden-import=secret2 \
--upx-dir=/usr/local/share/ \
myscript.spec
Or in Windows, use the little-known BAT file line continuation:
pyinstaller --noconfirm --log-level=WARN ^
--onefile --nowindow ^
--add-data="README;." ^
--add-data="image1.png;img" ^
--add-binary="libfoo.so;lib" ^
--hidden-import=secret1 ^
--hidden-import=secret2 ^
--icon=..\MLNMFLCN.ICO ^
myscript.spec
Running PyInstaller from Python code¶
If you want to run PyInstaller from Python code, you can use the run
function
defined in PyInstaller.__main__
. For instance, the following code:
import PyInstaller.__main__
PyInstaller.__main__.run([
'my_script.py',
'--onefile',
'--windowed'
])
Is equivalent to:
pyinstaller my_script.py --onefile --windowed
Using UPX¶
UPX is a free utility available for most operating systems. UPX compresses executable files and libraries, making them smaller, sometimes much smaller. UPX is available for most operating systems and can compress a large number of executable file formats. See the UPX home page for downloads, and for the list of supported executable formats.
A compressed executable program is wrapped in UPX startup code that dynamically decompresses the program when the program is launched. After it has been decompressed, the program runs normally. In the case of a PyInstaller one-file executable that has been UPX-compressed, the full execution sequence is:
The compressed program start up in the UPX decompressor code.
After decompression, the program executes the PyInstaller bootloader, which creates a temporary environment for Python.
The Python interpreter executes your script.
PyInstaller looks for UPX on the execution path
or the path specified with the --upx-dir
option.
If UPX exists, PyInstaller applies it to the final executable,
unless the --noupx
option was given.
UPX has been used with PyInstaller output often, usually with no problems.
Encrypting Python Bytecode¶
To encrypt the Python bytecode modules stored in the bundle,
pass the --key
=key-string argument on
the command line.
For this to work, you need to run:
pip install pyinstaller[encryption]
The key-string is a string of 16 characters which is used to encrypt each file of Python byte-code before it is stored in the archive inside the executable file.
This feature uses the tinyaes module internally for the encryption.
Splash Screen (Experimental)¶
Note
This feature is incompatible with macOS. In the current design, the splash screen operates in a secondary thread, which is disallowed by the Tcl/Tk (or rather, the underlying GUI toolkit) on macOS.
Some applications may require a splash screen as soon as the application (bootloader) has been started, because especially in onefile mode large applications may have long extraction/startup times, while the bootloader prepares everything, where the user cannot judge whether the application was started successfully or not.
The bootloader is able to display a one-image (i.e. only an image) splash screen, which is displayed before the actual main extraction process starts. The splash screen supports non-transparent and hard-cut-transparent images as background image, so non-rectangular splash screens can also be displayed.
This splash screen is based on Tcl/Tk, which is the same library used by the Python module tkinter. PyInstaller bundles the dynamic libraries of tcl and tk into the application at compile time. These are loaded into the bootloader at startup of the application after they have been extracted (if the program has been packaged as an onefile archive). Since the file sizes of the necessary dynamic libraries are very small, there is almost no delay between the start of the application and the splash screen. The compressed size of the files necessary for the splash screen is about 1.5 MB.
As an additional feature, text can optionally be displayed on the splash screen. This can be changed/updated from within Python. This offers the possibility to display the splash screen during longer startup procedures of a Python program (e.g. waiting for a network response or loading large files into memory). You can also start a GUI behind the splash screen, and only after it is completely initialized the splash screen can be closed. Optionally, the font, color and size of the text can be set. However, the font must be installed on the user system, as it is not bundled. If the font is not available, a fallback font is used.
If the splash screen is configured to show text, it will automatically (as onefile archive) display the name of the file that is currently being unpacked, this acts as a progress bar.
The pyi_splash
Module¶
The splash screen is controlled from within Python by the pyi_splash
module, which can
be imported at runtime. This module cannot be installed by a package manager
because it is part of PyInstaller and is included as needed.
This module must be imported within the Python program. The usage is as follows:
import pyi_splash
# Update the text on the splash screen
pyi_splash.update_text("PyInstaller is a great software!")
pyi_splash.update_text("Second time's a charm!")
# Close the splash screen. It does not matter when the call
# to this function is made, the splash screen remains open until
# this function is called or the Python program is terminated.
pyi_splash.close()
Of course the import should be in a try ... except
block, in case the program is
used externally as a normal Python script, without a bootloader.
For a detailed description see pyi_splash Module (Detailed).
Defining the Extraction Location¶
In rare cases, when you bundle to a single executable
(see Bundling to One File and How the One-File Program Works),
you may want to control the location of the temporary directory at compile
time. This can be done using the --runtime-tmpdir
option. If this option is
given, the bootloader will ignore any temp-folder location defined by the
run-time OS. Please use this option only if you know what you are doing.
Supporting Multiple Platforms¶
If you distribute your application for only one combination of OS and Python, just install PyInstaller like any other package and use it in your normal development setup.
Supporting Multiple Python Environments¶
When you need to bundle your application within one OS but for different versions of Python and support libraries – for example, a Python 3.6 version and a Python 3.7 version; or a supported version that uses Qt4 and a development version that uses Qt5 – we recommend you use venv. With venv you can maintain different combinations of Python and installed packages, and switch from one combination to another easily. These are called virtual environments or venvs in short.
Use venv to create as many different development environments as you need, each with its unique combination of Python and installed packages.
Install PyInstaller in each virtual environment.
Use PyInstaller to build your application in each virtual environment.
Note that when using venv, the path to the PyInstaller commands is:
Windows: ENV_ROOT\Scripts
Others: ENV_ROOT/bin
Under Windows, the pip-Win package makes it especially easy to set up different environments and switch between them. Under GNU/Linux and Mac OS, you switch environments at the command line.
See PEP 405 and the official Python Tutorial on Virtual Environments and Packages for more information about Python virtual environments.
Supporting Multiple Operating Systems¶
If you need to distribute your application for more than one OS, for example both Windows and Mac OS X, you must install PyInstaller on each platform and bundle your app separately on each.
You can do this from a single machine using virtualization. The free virtualBox or the paid VMWare and Parallels allow you to run another complete operating system as a “guest”. You set up a virtual machine for each “guest” OS. In it you install Python, the support packages your application needs, and PyInstaller.
A File Sync & Share system like NextCloud is useful with virtual machines. Install the synchronization client in each virtual machine, all linked to your synchronization account. Keep a single copy of your script(s) in a synchronized folder. Then on any virtual machine you can run PyInstaller thus:
cd ~/NextCloud/project_folder/src # GNU/Linux, Mac -- Windows similar
rm *.pyc # get rid of modules compiled by another Python
pyinstaller --workpath=path-to-local-temp-folder \
--distpath=path-to-local-dist-folder \
...other options as required... \
./myscript.py
PyInstaller reads scripts from the common synchronized folder, but writes its work files and the bundled app in folders that are local to the virtual machine.
If you share the same home directory on multiple platforms, for example GNU/Linux and OS X, you will need to set the PYINSTALLER_CONFIG_DIR environment variable to different values on each platform otherwise PyInstaller may cache files for one platform and use them on the other platform, as by default it uses a subdirectory of your home directory as its cache location.
It is said to be possible to cross-develop for Windows under GNU/Linux using the free Wine environment. Further details are needed, see How to Contribute.
Capturing Windows Version Data¶
A Windows app may require a Version resource file. A Version resource contains a group of data structures, some containing binary integers and some containing strings, that describe the properties of the executable. For details see the Microsoft Version Information Structures page.
Version resources are complex and
some elements are optional, others required.
When you view the version tab of a Properties dialog,
there’s no simple relationship between
the data displayed and the structure of the resource.
For this reason PyInstaller includes the pyi-grab_version
command.
It is invoked with the full path name of any Windows executable
that has a Version resource:
pyi-grab_version
executable_with_version_resource
The command writes text that represents
a Version resource in readable form to standard output.
You can copy it from the console window or redirect it to a file.
Then you can edit the version information to adapt it to your program.
Using pyi-grab_version
you can find an executable that displays the kind of
information you want, copy its resource data, and modify it to suit your package.
The version text file is encoded UTF-8 and may contain non-ASCII characters. (Unicode characters are allowed in Version resource string fields.) Be sure to edit and save the text file in UTF-8 unless you are certain it contains only ASCII string values.
Your edited version text file can be given with the --version-file
option to pyinstaller
or pyi-makespec
.
The text data is converted to a Version resource and
installed in the bundled app.
In a Version resource there are two 64-bit binary values,
FileVersion
and ProductVersion
.
In the version text file these are given as four-element tuples,
for example:
filevers=(2, 0, 4, 0),
prodvers=(2, 0, 4, 0),
The elements of each tuple represent 16-bit values
from most-significant to least-significant.
For example the value (2, 0, 4, 0)
resolves to
0002000000040000
in hex.
You can also install a Version resource from a text file after
the bundled app has been created, using the pyi-set_version
command:
pyi-set_version
version_text_file executable_file
The pyi-set_version
utility reads a version text file as written
by pyi-grab_version
, converts it to a Version resource,
and installs that resource in the executable_file specified.
For advanced uses, examine a version text file as written by pyi-grab_version
.
You find it is Python code that creates a VSVersionInfo
object.
The class definition for VSVersionInfo
is found in
utils/win32/versioninfo.py
in the PyInstaller distribution folder.
You can write a program that imports versioninfo
.
In that program you can eval
the contents of a version info text file to produce a
VSVersionInfo
object.
You can use the .toRaw()
method of that object to
produce a Version resource in binary form.
Or you can apply the unicode()
function to the object
to reproduce the version text file.
Building Mac OS X App Bundles¶
Under Mac OS X, PyInstaller always builds a UNIX executable in
dist
.
If you specify --onedir
, the output is a folder named myscript
containing supporting files and an executable named myscript
.
If you specify --onefile
, the output is a single UNIX executable
named myscript
.
Either executable can be started from a Terminal command line.
Standard input and output work as normal through that Terminal window.
If you specify --windowed
with either option, the dist
folder
also contains an OS X application named myscript.app
.
As you probably know, an application is a special type of folder.
The one built by PyInstaller contains a folder always named
Contents
which contains:
A folder
Frameworks
which is empty.A folder
Resources
that contains an icon file.A file
Info.plist
that describes the app.A folder
MacOS
that contains the the executable and supporting files, just as in the--onedir
folder.
Use the --icon
argument to specify a custom icon for the application.
It will be copied into the Resources
folder.
(If you do not specify an icon file, PyInstaller supplies a
file icon-windowed.icns
with the PyInstaller logo.)
Use the --osx-bundle-identifier
argument to add a bundle identifier.
This becomes the CFBundleIdentifier
used in code-signing
(see the PyInstaller code signing recipe
and for more detail, the Apple code signing overview technical note).
You can add other items to the Info.plist
by editing the spec file;
see Spec File Options for a Mac OS X Bundle below.
Platform-specific Notes¶
GNU/Linux¶
Making GNU/Linux Apps Forward-Compatible¶
Under GNU/Linux, PyInstaller does not bundle libc
(the C standard library, usually glibc
, the Gnu version) with the app.
Instead, the app expects to link dynamically to the libc
from the
local OS where it runs.
The interface between any app and libc
is forward compatible to
newer releases, but it is not backward compatible to older releases.
For this reason, if you bundle your app on the current version of GNU/Linux, it may fail to execute (typically with a runtime dynamic link error) if it is executed on an older version of GNU/Linux.
The solution is to always build your app on the oldest version of
GNU/Linux you mean to support.
It should continue to work with the libc
found on newer versions.
The GNU/Linux standard libraries such as glibc
are distributed in 64-bit
and 32-bit versions, and these are not compatible.
As a result you cannot bundle your app on a 32-bit system and run it
on a 64-bit installation, nor vice-versa.
You must make a unique version of the app for each word-length supported.
Windows¶
The developer needs to take special care to include the Visual C++ run-time .dlls: Python 3.5+ uses Visual Studio 2015 run-time, which has been renamed into “Universal CRT“ and has become part of Windows 10. For Windows Vista through Windows 8.1 there are Windows Update packages, which may or may not be installed in the target-system. So you have the following options:
Build on Windows 7 which has been reported to work.
Include one of the VCRedist packages (the redistributable package files) into your application’s installer. This is Microsoft’s recommended way, see “Distributing Software that uses the Universal CRT“ in the above-mentioned link, numbers 2 and 3.
Install the Windows Software Development Kit (SDK) for Windows 10 and expand the .spec-file to include the required DLLs, see “Distributing Software that uses the Universal CRT“ in the above-mentioned link, number 6.
If you think, PyInstaller should do this by itself, please help improving PyInstaller.
Mac OS X¶
Making Mac OS X apps Forward-Compatible¶
In Mac OS X, components from one version of the OS are usually compatible with later versions, but they may not work with earlier versions.
The only way to be certain your app supports an older version of Mac OS X is to run PyInstaller in the oldest version of the OS you need to support.
For example, to be sure of compatibility with “Snow Leopard” (10.6) and later versions, you should execute PyInstaller in that environment. You would create a copy of Mac OS X 10.6, typically in a virtual machine. In it, install the desired level of Python (the default Python in Snow Leopard was 2.6, which PyInstaller no longer supports), and install PyInstaller, your source, and all its dependencies. Then build your app in that environment. It should be compatible with later versions of Mac OS X.
Building 32-bit Apps in Mac OS X¶
Note
This section still refers to Python 2.7 provided by Apple. It might not be valid for Python 3 installed from MacPorts or Homebrew.
Please contribute to keep this section up-to-date.
Older versions of Mac OS X supported both 32-bit and 64-bit executables. PyInstaller builds an app using the the word-length of the Python used to execute it. That will typically be a 64-bit version of Python, resulting in a 64-bit executable. To create a 32-bit executable, run PyInstaller under a 32-bit Python.
Python as installed in OS X will usually be executable in either 64- or 32-bit mode.
To verify this, apply the file
command to the Python executable:
$ file /usr/local/bin/python3
/usr/local/bin/python3: Mach-O universal binary with 2 architectures
/usr/local/bin/python3 (for architecture i386): Mach-O executable i386
/usr/local/bin/python3 (for architecture x86_64): Mach-O 64-bit executable x86_64
The OS chooses which architecture to run, and typically defaults to 64-bit.
You can force the use of either architecture by name using the arch
command:
$ /usr/local/bin/python3
Python 3.4.2 (v3.4.2:ab2c023a9432, Oct 5 2014, 20:42:22)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys; sys.maxsize
9223372036854775807
$ arch -i386 /usr/local/bin/python3
Python 3.4.2 (v3.4.2:ab2c023a9432, Oct 5 2014, 20:42:22)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys; sys.maxsize
2147483647
Apple’s default /usr/bin/python
may circumvent the arch
specification and run 64-bit regardless.
(That is not the case if you apply arch
to a specific version
such as /usr/bin/python2.7
.)
To make sure of running 32-bit in all cases, set the following environment variable:
VERSIONER_PYTHON_PREFER_32_BIT=yes
arch -i386 /usr/bin/python pyinstaller --clean -F -w myscript.py
Getting the Opened Document Names¶
Note
Support for OpenDocument events is broken in PyInstaller 3.0 owing to code changes needed in the bootloader to support current versions of Mac OS X. Do not attempt to use this feature until it has been fixed. If this feature is important to you, follow and comment on the status of PyInstaller Issue #1309.
When a user double-clicks a document of a type your application supports, or when a user drags a document icon and drops it on your application’s icon, Mac OS X launches your application and provides the name(s) of the opened document(s) in the form of an OpenDocument AppleEvent. This AppleEvent is received by the bootloader before your code has started executing.
The bootloader gets the names of opened documents from
the OpenDocument event and encodes them into the argv
string before starting your code.
Thus your code can query sys.argv
to get the names
of documents that should be opened at startup.
OpenDocument is the only AppleEvent the bootloader handles. If you want to handle other events, or events that are delivered after the program has launched, you must set up the appropriate handlers.
AIX¶
Depending on whether Python was build as a 32-bit or a 64-bit executable
you may need to set or unset
the environment variable OBJECT_MODE
.
To determine the size the following command can be used:
$ python -c "import sys; print(sys.maxsize <= 2**32)"
True
When the answer is True
(as above) Python was build as a 32-bit
executable.
When working with a 32-bit Python executable proceed as follows:
$ unset OBJECT_MODE
$ pyinstaller <your arguments>
When working with a 64-bit Python executable proceed as follows:
$ export OBJECT_MODE=64
$ pyinstaller <your arguments>
Run-time Information¶
Your app should run in a bundle exactly as it does when run from source. However, you may want to learn at run-time whether the app is running from source or whether it is bundled (“frozen”). You can use the following code to check “are we bundled?”:
import sys
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
print('running in a PyInstaller bundle')
else:
print('running in a normal Python process')
When a bundled app starts up, the bootloader sets the sys.frozen
attribute and stores the absolute path to the bundle folder in
sys._MEIPASS
. For a one-folder bundle, this is the path to that folder. For
a one-file bundle, this is the path to the temporary folder created by the
bootloader (see How the One-File Program Works).
When your app is running, it may need to access data files in one of the following locations:
Files that were bundled with it (see Adding Data Files).
Files the user has placed with the app bundle, say in the same folder.
Files in the user’s current working directory.
The program has access to several variables for these uses.
Using __file__
¶
When your program is not bundled, the Python variable __file__
refers to
the current path of the module it is contained in. When importing a module
from a bundled script, the PyInstaller bootloader will set the module’s
__file__
attribute to the correct path relative to the bundle folder.
For example, if you import mypackage.mymodule
from a bundled script, then
the __file__
attribute of that module will be sys._MEIPASS +
'mypackage/mymodule.pyc'
. So if you have a data file at
mypackage/file.dat
that you added to the bundle at mypackage/file.dat
,
the following code will get its path (in both the non-bundled and the bundled
case):
from os import path
path_to_dat = path.abspath(path.join(path.dirname(__file__), 'file.dat'))
In the main script (the __main__
module) itself, the __file__
variable contains path to the script file. In Python 3.8 and earlier,
this path is either absolute or relative (depending on how the script
was passed to the python
interpreter), while in Python 3.9 and later,
it is always an absolute path. In the bundled script, the PyInstaller
bootloader always sets the __file__
variable inside the __main__
module to the absolute path inside the bundle directory, as if the
byte-compiled entry-point script existed there.
For example, if your entry-point script is called program.py
, then
the __file__
attribute inside the bundled script will point to
sys._MEIPASS + 'program.py'
. Therefore, locating a data file relative
to the main script can be either done directly using sys._MEIPASS
or
via the parent path of the __file__
inside the main script.
The following example will get the path to a file other-file.dat
located next to the main script if not bundled and inside the bundle folder
if it is bundled:
from os import path
bundle_dir = path.abspath(path.dirname(__file__))
path_to_dat = path.join(bundle_dir, 'other-file.dat')
Or, if you’d rather use pathlib:
from pathlib import Path
bundle_dir = Path(__file__).parent
path_to_dat = Path.cwd() / bundle_dir / "other-file.dat"
Changed in version 4.3: Formerly, the __file__
attribute of the entry-point script
(the __main__
module) was set to only its basename rather than
its full (absolute or relative) path within the bundle directory.
Therefore, PyInstaller documentation used to suggest sys._MEIPASS
as means for locating resources relative to the bundled entry-point
script. Now, __file__
is always set to the absolute full path,
and is the preferred way of locating such resources.
Placing data files at expected locations inside the bundle¶
To place the data-files where your code expects them to be (i.e., relative
to the main script or bundle directory), you can use the dest parameter
of the --add-data=source:dest
command-line switches.
Assuming you normally
use the following code in a file named my_script.py
to locate a file
file.dat
in the same folder:
from os import path
path_to_dat = path.abspath(path.join(path.dirname(__file__), 'file.dat'))
Or the pathlib equivalent:
from pathlib import Path
path_to_dat = (Path.cwd() / __file__).with_name("file.dat")
And my_script.py
is not part of a package (not in a folder containing
an __init_.py
), then __file__
will be [app root]/my_script.pyc
meaning that if you put file.dat
in the root of your package, using:
PyInstaller --add-data=/path/to/file.dat:.
It will be found correctly at runtime without changing my_script.py
.
Note
Windows users should use ;
instead of :
in the above line.
If __file__
is checked from inside a package or library (say
my_library.data
) then __file__
will be
[app root]/my_library/data.pyc
and --add-data
should mirror that:
PyInstaller --add-data=/path/to/my_library/file.dat:./my_library
However, in this case it is much easier to switch to the spec file and use the
PyInstaller.utils.hooks.collect_data_files()
helper function:
from PyInstaller.utils.hooks import collect_data_files
a = Analysis(...,
datas=collect_data_files("my_library"),
...)
Using sys.executable
and sys.argv[0]
¶
When a normal Python script runs, sys.executable
is the path to the
program that was executed, namely, the Python interpreter.
In a frozen app, sys.executable
is also the path to the
program that was executed, but that is not Python;
it is the bootloader in either the one-file app
or the executable in the one-folder app.
This gives you a reliable way to locate the frozen executable the user
actually launched.
The value of sys.argv[0]
is the name or relative path that was
used in the user’s command.
It may be a relative path or an absolute path depending
on the platform and how the app was launched.
If the user launches the app by way of a symbolic link,
sys.argv[0]
uses that symbolic name,
while sys.executable
is the actual path to the executable.
Sometimes the same app is linked under different names
and is expected to behave differently depending on the name that is
used to launch it.
For this case, you would test os.path.basename(sys.argv[0])
On the other hand, sometimes the user is told to store the executable
in the same folder as the files it will operate on,
for example a music player that should be stored in the same folder
as the audio files it will play.
For this case, you would use os.path.dirname(sys.executable)
.
The following small program explores some of these possibilities.
Save it as directories.py
.
Execute it as a Python script,
then bundled as a one-folder app.
Then bundle it as a one-file app and launch it directly and also via a
symbolic link:
#!/usr/bin/env python3
import sys, os
frozen = 'not'
if getattr(sys, 'frozen', False):
# we are running in a bundle
frozen = 'ever so'
bundle_dir = sys._MEIPASS
else:
# we are running in a normal Python environment
bundle_dir = os.path.dirname(os.path.abspath(__file__))
print( 'we are',frozen,'frozen')
print( 'bundle dir is', bundle_dir )
print( 'sys.argv[0] is', sys.argv[0] )
print( 'sys.executable is', sys.executable )
print( 'os.getcwd is', os.getcwd() )
LD_LIBRARY_PATH / LIBPATH considerations¶
This environment variable is used to discover libraries, it is the library search path - on GNU/Linux and *BSD LD_LIBRARY_PATH is used, on AIX it is LIBPATH.
If it exists, PyInstaller saves the original value to *_ORIG, then modifies the search path so that the bundled libraries are found first by the bundled code.
But if your code executes a system program, you often do not want that this system program loads your bundled libraries (that are maybe not compatible with your system program) - it rather should load the correct libraries from the system locations like it usually does.
Thus you need to restore the original path before creating the subprocess with the system program.
env = dict(os.environ) # make a copy of the environment
lp_key = 'LD_LIBRARY_PATH' # for GNU/Linux and *BSD.
lp_orig = env.get(lp_key + '_ORIG')
if lp_orig is not None:
env[lp_key] = lp_orig # restore the original, unmodified value
else:
# This happens when LD_LIBRARY_PATH was not set.
# Remove the env var as a last resort:
env.pop(lp_key, None)
p = Popen(system_cmd, ..., env=env) # create the process
Using Spec Files¶
When you execute
pyinstaller
options..myscript.py
the first thing PyInstaller does is to build a spec (specification) file
myscript.spec
.
That file is stored in the --specpath
directory,
by default the current directory.
The spec file tells PyInstaller how to process your script.
It encodes the script names and most of the options
you give to the pyinstaller
command.
The spec file is actually executable Python code.
PyInstaller builds the app by executing the contents of the spec file.
For many uses of PyInstaller you do not need to examine or modify the spec file.
It is usually enough to
give all the needed information (such as hidden imports)
as options to the pyinstaller
command and let it run.
There are four cases where it is useful to modify the spec file:
When you want to bundle data files with the app.
When you want to include run-time libraries (
.dll
or.so
files) that PyInstaller does not know about from any other source.When you want to add Python run-time options to the executable.
When you want to create a multiprogram bundle with merged common modules.
These uses are covered in topics below.
You create a spec file using this command:
pyi-makespec
optionsname.py
[other scripts …]
The options are the same options documented above
for the pyinstaller
command.
This command creates the name.spec
file but does not
go on to build the executable.
After you have created a spec file and modified it as necessary,
you build the application by passing the spec file to the pyinstaller
command:
pyinstaller
optionsname.spec
When you create a spec file, most command options are encoded in the spec file. When you build from a spec file, those options cannot be changed. If they are given on the command line they are ignored and replaced by the options in the spec file.
Only the following command-line options have an effect when building from a spec file:
Spec File Operation¶
After PyInstaller creates a spec file,
or opens a spec file when one is given instead of a script,
the pyinstaller
command executes the spec file as code.
Your bundled application is created by the execution of the spec file.
The following is a shortened example of a spec file for a minimal, one-folder app:
block_cipher = None
a = Analysis(['minimal.py'],
pathex=['/Developer/PItests/minimal'],
binaries=None,
datas=None,
hiddenimports=[],
hookspath=None,
runtime_hooks=None,
excludes=None,
cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,... )
coll = COLLECT(...)
The statements in a spec file create instances of four classes,
Analysis
, PYZ
, EXE
and COLLECT
.
A new instance of class
Analysis
takes a list of script names as input. It analyzes all imports and other dependencies. The resulting object (assigned toa
) contains lists of dependencies in class members named:scripts
: the python scripts named on the command line;pure
: pure python modules needed by the scripts;pathex
: a list of paths to search for imports (like usingPYTHONPATH
), including paths given by the--paths
option.binaries
: non-python modules needed by the scripts, including names given by the--add-binary
option;datas
: non-binary files included in the app, including names given by the--add-data
option.
An instance of class
PYZ
is a.pyz
archive (described under Inspecting Archives below), which contains all the Python modules froma.pure
.An instance of
EXE
is built from the analyzed scripts and thePYZ
archive. This object creates the executable file.An instance of
COLLECT
creates the output folder from all the other parts.
In one-file mode, there is no call to COLLECT
, and the
EXE
instance receives all of the scripts, modules and binaries.
You modify the spec file to pass additional values to Analysis
and
to EXE
.
Adding Files to the Bundle¶
To add files to the bundle, you create a list that describes the files
and supply it to the Analysis
call.
When you bundle to a single folder (see Bundling to One Folder),
the added data files are copied into the folder with the executable.
When you bundle to a single executable (see Bundling to One File),
copies of added files are compressed into the executable, and expanded to the
_MEIxxxxxx
temporary folder before execution.
This means that any changes a one-file executable makes to an added file
will be lost when the application ends.
In either case, to find the data files at run-time, see Run-time Information.
Adding Data Files¶
You can add data files to the bundle by using the --add-data
command option, or by
adding them as a list to the spec file.
When using the spec file, provide a list that
describes the files as the value of the datas=
argument to Analysis
.
The list of data files is a list of tuples.
Each tuple has two values, both of which must be strings:
The first string specifies the file or files as they are in this system now.
The second specifies the name of the folder to contain the files at run-time.
For example, to add a single README file to the top level of a one-folder app, you could modify the spec file as follows:
a = Analysis(...
datas=[ ('src/README.txt', '.') ],
...
)
And the command line equivalent (see What To Bundle, Where To Search for platform-specific details):
pyinstaller --add-data 'src/README.txt:.' myscript.py
You have made the datas=
argument a one-item list.
The item is a tuple in which the first string says the existing file
is src/README.txt
.
That file will be looked up (relative to the location of the spec file)
and copied into the top level of the bundled app.
The strings may use either /
or \
as the path separator character.
You can specify input files using “glob” abbreviations.
For example to include all the .mp3
files from a certain folder:
a = Analysis(...
datas= [ ('/mygame/sfx/*.mp3', 'sfx' ) ],
...
)
All the .mp3
files in the folder /mygame/sfx
will be copied
into a folder named sfx
in the bundled app.
The spec file is more readable if you create the list of added files in a separate statement:
added_files = [
( 'src/README.txt', '.' ),
( '/mygame/sfx/*.mp3', 'sfx' )
]
a = Analysis(...
datas = added_files,
...
)
You can also include the entire contents of a folder:
added_files = [
( 'src/README.txt', '.' ),
( '/mygame/data', 'data' ),
( '/mygame/sfx/*.mp3', 'sfx' )
]
The folder /mygame/data
will be reproduced under the name
data
in the bundle.
Using Data Files from a Module¶
If the data files you are adding are contained within a Python module,
you can retrieve them using pkgutil.get_data()
.
For example, suppose that part of your application is a module named helpmod
.
In the same folder as your script and its spec file you have this folder
arrangement:
helpmod
__init__.py
helpmod.py
help_data.txt
Because your script includes the statement import helpmod
,
PyInstaller will create this folder arrangement in your bundled app.
However, it will only include the .py
files.
The data file help_data.txt
will not be automatically included.
To cause it to be included also, you would add a datas
tuple
to the spec file:
a = Analysis(...
datas= [ ('helpmod/help_data.txt', 'helpmod' ) ],
...
)
When your script executes, you could find help_data.txt
by
using its base folder path, as described in the previous section.
However, this data file is part of a module, so you can also retrieve
its contents using the standard library function pkgutil.get_data()
:
import pkgutil
help_bin = pkgutil.get_data( 'helpmod', 'help_data.txt' )
This returns the contents of the help_data.txt
file as a binary string.
If it is actually characters, you must decode it:
help_utf = help_bin.decode('UTF-8', 'ignore')
Adding Binary Files¶
Note
Binary files refers to DLLs, dynamic libraries, shared
object-files, and such, which PyInstaller is going to search for further
binary dependencies. Files like images and PDFs should go into the
datas
.
You can add binary files to the bundle by using the --add-binary
command option,
or by adding them as a list to the spec file.
In the spec file, make a list of tuples that describe the files needed.
Assign the list of tuples to the binaries=
argument of Analysis.
Adding binary files works in a similar way as adding data files. As described in Adding Binary Files, each tuple should have two values:
The first string specifies the file or files as they are in this system now.
The second specifies the name of the folder to contain the files at run-time.
Normally PyInstaller learns about .so
and .dll
libraries by
analyzing the imported modules.
Sometimes it is not clear that a module is imported;
in that case you use a --hidden-import
command option.
But even that might not find all dependencies.
Suppose you have a module special_ops.so
that is written in C
and uses the Python C-API.
Your program imports special_ops
, and PyInstaller finds and
includes special_ops.so
.
But perhaps special_ops.so
links to libiodbc.2.dylib
.
PyInstaller does not find this dependency.
You could add it to the bundle this way:
a = Analysis(...
binaries=[ ( '/usr/lib/libiodbc.2.dylib', '.' ) ],
...
Or via the command line (again, see What To Bundle, Where To Search for platform-specific details):
pyinstaller --add-binary '/usr/lib/libiodbc.2.dylib:.' myscript.py
If you wish to store libiodbc.2.dylib
on a specific folder inside the bundle,
for example vendor
, then you could specify it, using the second element of the tuple:
a = Analysis(...
binaries=[ ( '/usr/lib/libiodbc.2.dylib', 'vendor' ) ],
...
As with data files, if you have multiple binary files to add, to improve readability, create the list in a separate statement and pass the list by name.
Advanced Methods of Adding Files¶
PyInstaller supports a more advanced (and complex) way of adding files to the bundle that may be useful for special cases. See The TOC and Tree Classes below.
Giving Run-time Python Options¶
You can pass command-line options to the Python interpreter. The interpreter takes a number of command-line options but only the following are supported for a bundled app:
v
to write a message to stdout each time a module is initialized.u
for unbuffered stdio.W
and an option to change warning behavior:W ignore
orW once
orW error
.
To pass one or more of these options, create a list of tuples, one for each option, and pass the list as an additional argument to the EXE call. Each tuple has three elements:
The option as a string, for example
v
orW ignore
.None
The string
OPTION
For example modify the spec file this way:
options = [ ('v', None, 'OPTION'), ('W ignore', None, 'OPTION') ]
a = Analysis( ...
)
...
exe = EXE(pyz,
a.scripts,
options, <--- added line
exclude_binaries=...
)
Note
The unbuffered stdio mode (the u
option) enables unbuffered
binary layer of stdout
and stderr
streams on all supported Python
versions. The unbuffered text layer requires Python 3.7 or later.
Spec File Options for a Mac OS X Bundle¶
When you build a windowed Mac OS X app
(that is, running in Mac OS X, you specify the --onefile
--windowed
options),
the spec file contains an additional statement to
create the Mac OS X application bundle, or app folder:
app = BUNDLE(exe,
name='myscript.app',
icon=None,
bundle_identifier=None)
The icon=
argument to BUNDLE
will have the path to an icon file
that you specify using the --icon
option.
The bundle_identifier
will have the value you specify with the
--osx-bundle-identifier
option.
An Info.plist
file is an important part of a Mac OS X app bundle.
(See the Apple bundle overview for a discussion of the contents
of Info.plist
.)
PyInstaller creates a minimal Info.plist
.
The version
option can be used to set the application version
using the CFBundleShortVersionString Core Foundation Key.
You can add or overwrite entries in the plist by passing an
info_plist=
parameter to the BUNDLE call. Its argument should be a
Python dict with keys and values to be included in the Info.plist
file.
PyInstaller creates Info.plist
from the info_plist dict
using the Python Standard Library module plistlib.
plistlib can handle nested Python objects (which are translated to nested
XML), and translates Python data types to the proper Info.plist
XML types. Here’s an example:
app = BUNDLE(exe,
name='myscript.app',
icon=None,
bundle_identifier=None,
version='0.0.1',
info_plist={
'NSPrincipalClass': 'NSApplication',
'NSAppleScriptEnabled': False,
'CFBundleDocumentTypes': [
{
'CFBundleTypeName': 'My File Format',
'CFBundleTypeIconFile': 'MyFileIcon.icns',
'LSItemContentTypes': ['com.example.myformat'],
'LSHandlerRank': 'Owner'
}
]
},
)
In the above example, the key/value 'NSPrincipalClass': 'NSApplication'
is
necessary to allow Mac OS X to render applications using retina resolution.
The key 'NSAppleScriptEnabled'
is assigned the Python boolean
False
, which will be output to Info.plist
properly as <false/>
.
Finally the key CFBundleDocumentTypes
tells Mac OS X what filetypes your
application supports (see Apple document types).
POSIX Specific Options¶
By default all required system libraries are bundled.
To exclude all or most non-Python shared system libraries from the bundle,
you can add a call to the function exclude_system_libraries
from the Analysis class.
System libraries are defined as files that come from under /lib*
or
/usr/lib*
as is the case on POSIX and related operating systems.
The function accepts an optional parameter
that is a list of file wildcards exceptions,
to not exclude library files that match those wildcards in the bundle.
For example to exclude all non-Python system libraries except “libexpat”
and anything containing “krb” use this:
a = Analysis(...)
a.exclude_system_libraries(list_of_exceptions=['libexpat*', '*krb*'])
The Splash
Target¶
For a splash screen to be displayed by the bootloader, the Splash
target must be called
at build time. This class can be added when the spec file is created with the command-line
option --splash IMAGE_FILE
. By default, the option to
display the optional text is disabled
(text_pos=None
). For more information about the splash screen, see Splash Screen (Experimental)
section. The Splash
Target looks like this:
a = Analysis(...)
splash = Splash('image.png',
binaries=a.binaries,
datas=a.datas,
text_pos=(10, 50),
text_size=12,
text_color='black')
Splash bundles the required resources for the splash screen into a file, which will be included in the CArchive.
A Splash
has two outputs, one is itself and one is stored in
splash.binaries
. Both need to be passed on to other build targets in
order to enable the splash screen.
To use the splash screen in a onefile application, please follow this example:
a = Analysis(...)
splash = Splash(...)
# onefile
exe = EXE(pyz,
a.scripts,
splash, # <-- both, splash target
splash.binaries, # <-- and splash binaries
...)
In order to use the splash screen in a onedir application, only a small change needs
to be made. The splash.binaries
attribute has to be moved into the COLLECT
target,
since the splash binaries do not need to be included into the executable:
a = Analysis(...)
splash = Splash(...)
# onedir
exe = EXE(pyz,
splash, # <-- splash target
a.scripts,
...)
coll = COLLECT(exe,
splash.binaries, # <-- splash binaries
...)
On Windows/macOS images with per-pixel transparency are supported. This allows non-rectengular splash screen images. On Windows the transparent borders of the image are hard-cuted, meaning that fading transparent values are not supported. There is no common implementation for non-rectengular windows on Linux, so images with per- pixel transparency is not supported.
The splash target can be configured in various ways. The constructor of the Splash
target is as follows:
- Splash.__init__(image_file, binaries, datas, **kwargs)¶
- Parameters
image_file (str) –
A path-like object to the image to be used. Only the PNG file format is supported.
Note
If a different file format is supplied and PIL (Pillow) is installed, the file will be converted automatically.
Note
Windows: Due to the implementation, the color Magenta/ RGB(255, 0, 255) must not be used in the image or text.
Note
If PIL (Pillow) is installed and the image is bigger than max_img_size, the image will be resized to fit into the specified area.
binaries (TOC) – The TOC of binaries the Analysis build target found. This TOC includes all extensionmodules and their dependencies. This is required to figure out, if the users program uses tkinter.
datas (TOC) – The TOC of data the Analysis build target found. This TOC includes all data-file dependencies of the modules. This is required to check if all splash screen requirements can be bundled.
- Keyword Arguments
text_pos – An optional 2x integer tuple that represents the origin of the text on the splash screen image. The origin of the text is its lower left corner. A unit in the respective coordinate system is a pixel of the image, its origin lies in the top left corner of the image. This parameter also acts like a switch for the text feature. If omitted, no text will be displayed on the splash screen. This text will be used to show textual progress in onefile mode.
text_size – The desired size of the font. If the size argument is a positive number, it is interpreted as a size in points. If size is a negative number, its absolute value is interpreted as a size in pixels. Default:
12
text_font – An optional name of a font for the text. This font must be installed on the user system, otherwise the system default font is used. If this parameter is omitted, the default font is also used.
text_color – An optional color for the text. Either RGB HTML notation or color names are supported. Default: black (Windows: Due to a implementation issue the color magenta/ rgb(255, 0, 255) is forbidden)
text_default – The default text which will be displayed before the extraction starts. Default: “Initializing”
full_tk – By default Splash bundles only the necessary files for the splash screen (some tk components). This options enables adding full tk and making it a requirement, meaning all tk files will be unpacked before the splash screen can be started. This is useful during development of the splash screen script. Default:
False
minify_script – The splash screen is created by executing an Tcl/Tk script. This option enables minimizing the script, meaning removing all non essential parts from the script. Default: True
rundir – The folder name in which tcl/tk will be extracted at runtime. There should be no matching folder in your application to avoid conflicts. Default:
__splash
name – An optional alternative filename for the .res file. If not specified, a name is generated.
script_name – An optional alternative filename for the Tcl script, that will be generated. If not specified, a name is generated.
max_img_size – Maximum size of the splash screen image as a tuple. If the supplied image exceeds this limit, it will be resized to fit the maximum width (to keep the original aspect ratio). This option can be disabled by setting it to None. Default: (760, 480)
Multipackage Bundles¶
Some products are made of several different apps, each of which might depend on a common set of third-party libraries, or share code in other ways. When packaging such a product it would be a pity to treat each app in isolation, bundling it with all its dependencies, because that means storing duplicate copies of code and libraries.
You can use the multipackage feature to bundle a set of executable apps so that they share single copies of libraries. You can do this with either one-file or one-folder apps. Each dependency (a DLL, for example) is packaged only once, in one of the apps. Any other apps in the set that depend on that DLL have an “external reference” to it, telling them to extract that dependency from the executable file of the app that contains it.
This saves disk space because each dependency is stored only once. However, to follow an external reference takes extra time when an app is starting up. All but one of the apps in the set will have slightly slower launch times.
The external references between binaries include hard-coded paths to the output directory, and cannot be rearranged. If you use one-folder mode, you must install all the application folders within a single parent directory. If you use one-file mode, you must place all the related applications in the same directory when you install the application.
To build such a set of apps you must code a custom
spec file that contains a call to the MERGE
function.
This function takes a list of analyzed scripts,
finds their common dependencies, and modifies the analyses
to minimize the storage cost.
The order of the analysis objects in the argument list matters. The MERGE function packages each dependency into the first script from left to right that needs that dependency. A script that comes later in the list and needs the same file will have an external reference to the prior script in the list. You might sequence the scripts to place the most-used scripts first in the list.
A custom spec file for a multipackage bundle contains one call to the MERGE function:
MERGE(*args)
MERGE is used after the analysis phase and before EXE
and COLLECT
.
Its variable-length list of arguments consists of
a list of tuples, each tuple having three elements:
The first element is an Analysis object, an instance of class Analysis, as applied to one of the apps.
The second element is the script name of the analyzed app (without the
.py
extension).The third element is the name for the executable (usually the same as the script).
MERGE examines the Analysis objects to learn the dependencies of each script. It modifies these objects to avoid duplication of libraries and modules. As a result the packages generated will be connected.
Example MERGE spec file¶
One way to construct a spec file for a multipackage bundle is to
first build a spec file for each app in the package.
Suppose you have a product that comprises three apps named
(because we have no imagination) foo
, bar
and zap
:
pyi-makespec
options as appropriate…foo.py
pyi-makespec
options as appropriate…bar.py
pyi-makespec
options as appropriate…zap.py
Check for warnings and test each of the apps individually.
Deal with any hidden imports and other problems.
When all three work correctly,
combine the statements from the three files foo.spec
,
bar.spec
and zap.spec
as follows.
First copy the Analysis statements from each, changing them to give each Analysis object a unique name:
foo_a = Analysis(['foo.py'],
pathex=['/the/path/to/foo'],
hiddenimports=[],
hookspath=None)
bar_a = Analysis(['bar.py'], etc., etc...
zap_a = Analysis(['zap.py'], etc., etc...
Now call the MERGE method to process the three Analysis objects:
MERGE( (foo_a, 'foo', 'foo'), (bar_a, 'bar', 'bar'), (zap_a, 'zap', 'zap') )
The Analysis objects foo_a
, bar_a
, and zap_a
are modified
so that the latter two refer to the first for common dependencies.
Following this you can copy the PYZ
, EXE
and COLLECT
statements from
the original three spec files,
substituting the unique names of the Analysis objects
where the original spec files have a.
, for example:
foo_pyz = PYZ(foo_a.pure)
foo_exe = EXE(foo_pyz, foo_a.scripts, ... etc.
foo_coll = COLLECT( foo_exe, foo_a.binaries, foo_a.datas... etc.
bar_pyz = PYZ(bar_a.pure)
bar_exe = EXE(bar_pyz, bar_a.scripts, ... etc.
bar_coll = COLLECT( bar_exe, bar_a.binaries, bar_a.datas... etc.
(If you are building one-file apps, there is no COLLECT
step.)
Save the combined spec file as foobarzap.spec
and then build it:
pyi-build foobarzap.spec
The output in the dist
folder will be all three apps, but
the apps dist/bar/bar
and dist/zap/zap
will refer to
the contents of dist/foo/
for shared dependencies.
There are several multipackage examples in the
PyInstaller distribution folder under tests/functional/specs
.
Remember that a spec file is executable Python.
You can use all the Python facilities (for
and with
and the members of sys
and io
)
in creating the Analysis
objects and performing the PYZ
, EXE
and COLLECT
statements.
You may also need to know and use The TOC and Tree Classes described below.
Globals Available to the Spec File¶
While a spec file is executing it has access to a limited set of global names.
These names include the classes defined by PyInstaller:
Analysis
, BUNDLE
, COLLECT
, EXE
, MERGE
,
PYZ
, TOC
, Tree
and Splash
,
which are discussed in the preceding sections.
Other globals contain information about the build environment:
DISTPATH
The relative path to the
dist
folder where the application will be stored. The default path is relative to the current directory. If the--distpath
option is used,DISTPATH
contains that value.HOMEPATH
The absolute path to the PyInstaller distribution, typically in the current Python site-packages folder.
SPEC
The complete spec file argument given to the
pyinstaller
command, for examplemyscript.spec
orsource/myscript.spec
.SPECPATH
The path prefix to the
SPEC
value as returned byos.path.split()
.specnm
The name of the spec file, for example
myscript
.workpath
The path to the
build
directory. The default is relative to the current directory. If theworkpath=
option is used,workpath
contains that value.WARNFILE
The full path to the warnings file in the build directory, for example
build/warn-myscript.txt
.
Notes about specific Features¶
This sections describes details about specific features. For a full list of features please refer to the website.
Ctypes Dependencies¶
Ctypes is a foreign function library for Python, that allows calling functions present in shared libraries. Those libraries are not imported as Python packages, because they are not picked up via Python imports: their path is passed to ctypes instead, which deals with the shared library directly; this caused <1.4 PyInstaller import detect machinery to miss those libraries, failing the goal to build self-contained PyInstaller executables:
from ctypes import *
# This will pass undetected under PyInstaller detect machinery,
# because it's not a direct import.
handle = CDLL("/usr/lib/library.so")
handle.function_call()
Solution in PyInstaller¶
PyInstaller contains a pragmatic implementation of Ctypes dependencies: it will search for simple standard usages of ctypes and automatically track and bundle the referenced libraries. The following usages will be correctly detected:
CDLL("library.so")
WinDLL("library.so")
ctypes.DLL("library.so")
cdll.library # Only valid under Windows - a limitation of ctypes, not PyInstaller's
windll.library # Only valid under Windows - a limitation of ctypes, not PyInstaller's
cdll.LoadLibrary("library.so")
windll.LoadLibrary("library.so")
More in detail, the following restrictions apply:
only libraries referenced by bare filenames (e.g. no leading paths) will be handled; handling absolute paths would be impossible without modifying the bytecode as well (remember that while running frozen, ctypes would keep searching the library at that very absolute location, whose presence on the host system nobody can guarantee), and relative paths handling would require recreating in the frozen executable the same hierarchy of directories leading to the library, in addition of keeping track of which the current working directory is;
only library paths represented by a literal string will be detected and included in the final executable: PyInstaller import detection works by inspecting raw Python bytecode, and since you can pass the library path to ctypes using a string (that can be represented by a literal in the code, but also by a variable, by the return value of an arbitrarily complex function, etc…), it’s not reasonably possible to detect all ctypes dependencies;
only libraries referenced in the same context of ctypes’ invocation will be handled.
We feel that it should be enough to cover most ctypes’ usages, with little or no modification required in your code.
If PyInstaller does not detect a library, you can add it to your
bundle by passing the respective information to --add-binary
option or
listing it in the .spec-file. If your frozen
application will be able to pick up the library at run-time can not be
guaranteed as it depends on the detailed implementation.
Gotchas¶
The ctypes detection system at Analysis time
is based on ctypes.util.find_library()
.
This means that you have to make sure
that while performing Analysis
and running frozen,
all the environment values find_library()
uses to search libraries
are aligned to those when running un-frozen.
Examples include using LD_LIBRARY_PATH
or DYLD_LIBRARY_PATH
to
widen find_library()
scope.
SWIG support¶
PyInstaller tries to detect binary modules created by SWIG. This detection requires:
The Python wrapper module must be imported somewhere in your application (or by any of the modules it uses).
The wrapper module must be available as source-code and it’s first line must contain the text
automatically generated by SWIG
.The C-module must have the same name as the wrapper module prefixed with an underscore (
_
). (This is a SWIG restriction already.)The C-module must sit just beside the wrapper module (thus a relative import would work).
Also some restrictions apply, due to the way the SWIG wrapper is implemented:
The C-module will become a global module. As a consequence, you can not use two SWIG modules with the same basename (e.g.
pkg1._cmod
andpkg2._cmod
), as one would overwrite the other.
Cython support¶
PyInstaller can follow import statements that refer to Cython C object modules and bundle them – like for any other module implemented in C.
But – again, as for any other module implemented in C – PyInstaller can not
determine if the Cython C object module is importing some Python module.
These will typically show up as in a traceback like this
(mind the .pyx
extension):
Traceback (most recent call last):
[…]
File "myapp\cython_module.pyx", line 3, in init myapp.cython_module
ModuleNotFoundError: No module named 'csv'
So if you are using a Cython C object module, which imports Python modules,
you will have to list these as --hidden-import
.
macOS multi-arch support¶
With the introduction of Apple Silicon M1, there are now several architecture options available for python:
single-arch
x86_64
with thin binaries: older python.org builds, Homebrew python running natively on Intel Macs or under rosetta2 on M1 Macssingle-arch
arm64
with thin binaries: Homebrew python running natively on M1 macsmulti-arch
universal2
with fat binaries (i.e., containing bothx86_64
andarm64
slices): recentuniversal2
python.org builds
PyInstaller aims to support all possible combinations stemming from the above options:
single-arch application created using corresponding single-arch python
universal2
application created usinguniversal2
pythonsingle-arch application created using
universal2
python (i.e., reducinguniversal2
fat binaries into eitherx86_64
orarm64
thin binaries)
By default, PyInstaller targets the current running architecture
and produces a single-arch binary (x86_64
when running on Intel Mac
or under rosetta2 on M1 Mac, or arm64
when running on M1 Mac). The
reason for that is that even with a universal2
python environment,
some packages may end up providing only single-arch binaries, making it
impossible to create a functional universal2
frozen application.
The alternative options, such as creating a universal2
version
of frozen application, or creating a non-native single-arch version using
universal2
environment, must therefore be explicitly enabled. This
can be done either by specifying the target architecture in the .spec
file via the target_arch=
argument to EXE()
, or on command-line
via the --target-arch
switch. Valid values are x86_64
, arm64
,
and universal2
.
Architecture validation during binary collection¶
To prevent run-time issues caused by missing or mismatched architecture slices in binaries, the binary collection process performs strict architecture validation. It checks whether collected binary files contain required arch slice(s), and if not, the build process is aborted with an error message about the problematic binary.
In such cases, creating frozen application for the selected target
architecture will not be possible unless the problem of missing arch slices
is manually addressed (for example, by downloading the wheel corresponding to
the missing architecture, and stiching the offending binary files together
using the lipo
utility).
Trimming fat binaries for single-arch targets¶
When targeting a single architecture, the build process extracts the
corresponding arch slice from any collected fat binaries, including the
bootloader. This results in a completely thin build even when building
in universal2
python environment.
macOS binary code signing¶
With Apple Silicon M1 architecture, macOS introduced mandatory code signing,
even if ad-hoc (i.e., without actual code-signing identity). This means
that arm64
arch slices (but possibly also x86_64
ones, especially
in universal2
binaries) in collected binaries always come with signature.
The processing of binaries done by PyInstaller (e.g., library path rewriting in binaries’ headers) invalidates their signatures. Therefore, the signatures need to be re-generated, otherwise the OS refuses to load a binary.
By default, PyInstaller ad-hoc (re)signs all collected binaries and
the generated executable itself. Instead of ad-hoc signing, it is also
possible to use real code-signing identity. To do so, either specify your
identity in the .spec
file via codesign_identity=
argument to
EXE()
, or on command-line via the --codesign-identity
switch.
Being able to provide codesign identity allows user to ensure that all
collected binaries in either onefile
or onedir
build are signed
with their identity. This is useful because for onefile
builds,
signing of embedded binaries cannot be performed in a post-processing step.
Note
When codesign identity is specified, PyInstaller also turns on
hardened runtime by passing --options=runtime
to the codesign
command. This requires the codesign identity to be a valid Apple-issued
code signing certificate, and will not work with self-signed certificates.
Trying to use self-signed certificate as a codesign identity will result in shared libraries failing to load, with the following reason reported:
[libname]: code signature in ([libname]) not valid for use in process using Library Validation: mapped file has no Team ID and is not a platform binary (signed with custom identity or adhoc?)
Furthermore, it is possible to specify entitlements file to be used
when signing the collected binaries and the executable. This can be
done in the .spec
file via entitlements_file=
argument to
EXE()
, or on command-line via the --osx-entitlements-file
switch.
App bundles¶
PyInstaller also automatically attempts to sign .app bundles, either
using ad-hoc identity or actual signing identity, if provided via
--codesign-identity
switch. In addition to passing same options as
when signing collected binaries (identity, hardened runtime, entitlement),
deep signing is also enabled via by passing --deep
option to the
codesign
utility.
Should the signing of the bundle fail for whatever reason, the error
message from the codesign
utility will be printed to the console,
along with a warning that manual intervention and manual signing of the
bundle are required.
When Things Go Wrong¶
The information above covers most normal uses of PyInstaller. However, the variations of Python and third-party libraries are endless and unpredictable. It may happen that when you attempt to bundle your app either PyInstaller itself, or your bundled app, terminates with a Python traceback. Then please consider the following actions in sequence, before asking for technical help.
Recipes and Examples for Specific Problems¶
The PyInstaller FAQ page has work-arounds for some common problems. Code examples for some advanced uses and some common problems are available on our PyInstaller Recipes page. Some of the recipes there include:
A more sophisticated way of collecting data files than the one shown above (Adding Files to the Bundle).
Bundling a typical Django app.
A use of a run-time hook to set the PyQt5 API level.
A workaround for a multiprocessing constraint under Windows.
and others. Many of these Recipes were contributed by users. Please feel free to contribute more recipes!
Finding out What Went Wrong¶
Build-time Messages¶
When the Analysis
step runs, it produces error and warning messages.
These display after the command line if the --log-level
option allows it.
Analysis also puts messages in a warnings file
named build/name/warn-name.txt
in the
work-path=
directory.
Analysis creates a message when it detects an import
and the module it names cannot be found.
A message may also be produced when a class or function is declared in
a package (an __init__.py
module), and the import specifies
package.name
. In this case, the analysis can’t tell if name is supposed to
refer to a submodule or package.
The “module not found” messages are not classed as errors because typically there are many of them. For example, many standard modules conditionally import modules for different platforms that may or may not be present.
All “module not found” messages are written to the
build/name/warn-name.txt
file.
They are not displayed to standard output because there are many of them.
Examine the warning file; often there will be dozens of modules not found,
but their absence has no effect.
When you run the bundled app and it terminates with an ImportError, that is the time to examine the warning file. Then see Helping PyInstaller Find Modules below for how to proceed.
Build-Time Dependency Graph¶
On each run PyInstaller writes a cross-referencing file about dependencies
into the build folder:
build/name/xref-name.html
in the
work-path=
directory is an HTML file that lists the full
contents of the import graph, showing which modules are imported
by which ones.
You can open it in any web browser.
Find a module name, then keep clicking the “imported by” links
until you find the top-level import that causes that module to be included.
If you specify --log-level=DEBUG
to the pyinstaller
command,
PyInstaller additionally generates a GraphViz input file representing the
dependency graph.
The file is build/name/graph-name.dot
in the
work-path=
directory.
You can process it with any GraphViz command, e.g. dot,
to produce
a graphical display of the import dependencies.
These files are very large because even the simplest “hello world” Python program ends up including a large number of standard modules. For this reason the graph file is not very useful in this release.
Build-Time Python Errors¶
PyInstaller sometimes terminates by raising a Python exception. In most cases the reason is clear from the exception message, for example “Your system is not supported”, or “Pyinstaller requires at least Python 3.6”. Others clearly indicate a bug that should be reported.
One of these errors can be puzzling, however:
IOError("Python library not found!")
PyInstaller needs to bundle the Python library, which is the
main part of the Python interpreter, linked as a dynamic load library.
The name and location of this file varies depending on the platform in use.
Some Python installations do not include a dynamic Python library
by default (a static-linked one may be present but cannot be used).
You may need to install a development package of some kind.
Or, the library may exist but is not in a folder where PyInstaller
is searching.
The places where PyInstaller looks for the python library are
different in different operating systems, but /lib
and /usr/lib
are checked in most systems.
If you cannot put the python library there,
try setting the correct path in the environment variable
LD_LIBRARY_PATH
in GNU/Linux or
DYLD_LIBRARY_PATH
in OS X.
Getting Debug Messages¶
The --debug=all
option (and its choices) provides a significant amount of diagnostic information.
This can be useful during development of a complex package,
or when your app doesn’t seem to be starting,
or just to learn how the runtime works.
Normally the debug progress messages go to standard output.
If the --windowed
option is used when bundling a Windows app,
they are sent to any attached debugger. If you are not using a debugger
(or don’t have one), the DebugView the free (beer) tool can be used to
display such messages. It has to be started before running the bundled
application.
For a --windowed
Mac OS app they are not displayed.
Consider bundling without --debug
for your production version.
Debugging messages require system calls and have an impact on performance.
Getting Python’s Verbose Imports¶
You can build the app with the --debug=imports
option
(see Getting Debug Messages above),
which will pass the -v
(verbose imports) flag
to the embedded Python interpreter.
This can be extremely useful.
It can be informative even with apps that are apparently working,
to make sure that they are getting all imports from the bundle,
and not leaking out to the local installed Python.
Python verbose and warning messages always go to standard output
and are not visible when the --windowed
option is used.
Remember to not use this for your production version.
Figuring Out Why Your GUI Application Won’t Start¶
If you are using the --windowed
option,
your bundled application may fail to start with an error message like
Failed to execute script my_gui
.
In this case, you will want to get more verbose output to find out
what is going on.
For Mac OS, you can run your application on the command line, i.e.``./dist/my_gui`` in Terminal instead of clicking on
my_gui.app
.For Windows, you will need to re-bundle your application without the
--windowed
option. Then you can run the resulting executable from the command line, i.e.:my_gui.exe
.For Unix and GNU/Linux there in no
--windowed
option. Anyway, if a your GUI application fails, you can run your application on the command line, i.e../dist/my_gui
.
This should give you the relevant error that is preventing your application from initializing, and you can then move on to other debugging steps.
Operation not permitted error¶
If you use the –onefile and it fails to run you program with error like:
./hello: error while loading shared libraries: libz.so.1:
failed to map segment from shared object: Operation not permitted
This can be caused by wrong permissions for the /tmp directory
(e.g. the filesystem is mounted with noexec
flags).
A simple way to solve this issue is to set,
in the environment variable TMPDIR,
a path to a directory in a filesystem mounted without noexec
flags, e.g.:
export TMPDIR=/var/tmp/
Helping PyInstaller Find Modules¶
Extending the Path¶
If Analysis recognizes that a module is needed, but cannot find that module,
it is often because the script is manipulating sys.path
.
The easiest thing to do in this case is to use the --paths
option
to list all the other places that the script might be searching for imports:
pyi-makespec --paths=/path/to/thisdir \
--paths=/path/to/otherdir myscript.py
These paths will be noted in the spec file in the pathex
argument.
They will be added to the current sys.path
during analysis.
Extending a Package’s __path__
¶
Python allows a script to extend the search path used for imports
through the __path__
mechanism.
Normally, the __path__
of an imported module has only one entry,
the directory in which the __init__.py
was found.
But __init__.py
is free to extend its __path__
to include other directories.
For example, the win32com.shell.shell
module actually resolves to
win32com/win32comext/shell/shell.pyd
.
This is because win32com/__init__.py
appends ../win32comext
to its __path__
.
Because the __init__.py
of an imported module
is not actually executed during analysis,
changes it makes to __path__
are not seen by PyInstaller.
We fix the problem with the same hook mechanism we use for hidden imports,
with some additional logic; see Understanding PyInstaller Hooks below.
Note that manipulations of __path__
hooked in this way apply only
to the Analysis.
At runtime all imports are intercepted and satisfied from within the
bundle. win32com.shell
is resolved the same
way as win32com.anythingelse
, and win32com.__path__
knows nothing of ../win32comext
.
Once in a while, that’s not enough.
Changing Runtime Behavior¶
More bizarre situations can be accomodated with runtime hooks. These are small scripts that manipulate the environment before your main script runs, effectively providing additional top-level code to your script.
There are two ways of providing runtime hooks.
You can name them with the option --runtime-hook
=path-to-script.
Second, some runtime hooks are provided.
At the end of an analysis,
the names in the module list produced by the Analysis phase are looked up in
loader/rthooks.dat
in the PyInstaller install folder.
This text file is the string representation of a
Python dictionary. The key is the module name, and the value is a list
of hook-script pathnames.
If there is a match, those scripts are included in the bundled app
and will be called before your main script starts.
Hooks you name with the option are executed
in the order given, and before any installed runtime hooks.
If you specify --runtime-hook=file1.py --runtime-hook=file2.py
then the execution order at runtime will be:
Code of
file1.py
.Code of
file2.py
.Any hook specified for an included module that is found in
rthooks/rthooks.dat
.Your main script.
Hooks called in this way, while they need to be careful of what they import,
are free to do almost anything.
One reason to write a run-time hook is to
override some functions or variables from some modules.
A good example of this is the Django runtime
hook (see loader/rthooks/pyi_rth_django.py
in the
PyInstaller folder).
Django imports some modules dynamically and it is looking
for some .py
files.
However .py
files are not available in the one-file bundle.
We need to override the function
django.core.management.find_commands
in a way that will just return a list of values.
The runtime hook does this as follows:
import django.core.management
def _find_commands(_):
return """cleanup shell runfcgi runserver""".split()
django.core.management.find_commands = _find_commands
Getting the Latest Version¶
If you have some reason to think you have found a bug in PyInstaller you can try downloading the latest development version. This version might have fixes or features that are not yet at PyPI. You can download the latest stable version and the latest development version from the PyInstaller Downloads page.
You can also install the latest version of PyInstaller directly using pip:
pip install https://github.com/pyinstaller/pyinstaller/archive/develop.zip
Asking for Help¶
When none of the above suggestions help, do ask for assistance on the PyInstaller Email List.
Then, if you think it likely that you see a bug in PyInstaller, refer to the How to Report Bugs page.
Advanced Topics¶
The following discussions cover details of PyInstaller internal methods. You should not need this level of detail for normal use, but such details are helpful if you want to investigate the PyInstaller code and possibly contribute to it, as described in How to Contribute.
The Bootstrap Process in Detail¶
There are many steps that must take place before the bundled script can begin execution. A summary of these steps was given in the Overview (How the One-Folder Program Works and How the One-File Program Works). Here is more detail to help you understand what the bootloader does and how to figure out problems.
Bootloader¶
The bootloader prepares everything for running Python code. It begins the setup and then returns itself in another process. This approach of using two processes allows a lot of flexibility and is used in all bundles except one-folder mode in Windows. So do not be surprised if you will see your bundled app as two processes in your system task manager.
What happens during execution of bootloader:
First process: bootloader starts.
If one-file mode, extract bundled files to
temppath/_MEIxxxxxx
.Modify various environment variables:
GNU/Linux: If set, save the original value of LD_LIBRARY_PATH into LD_LIBRARY_PATH_ORIG. Prepend our path to LD_LIBRARY_PATH.
AIX: same thing, but using LIBPATH and LIBPATH_ORIG.
OSX: unset DYLD_LIBRARY_PATH.
Set up to handle signals for both processes.
Run the child process.
Wait for the child process to finish.
If one-file mode, delete
temppath/_MEIxxxxxx
.
Second process: bootloader itself started as a child process.
On Windows set the activation context.
Load the Python dynamic library. The name of the dynamic library is embedded in the executable file.
Initialize Python interpreter: set sys.path, sys.prefix, sys.executable.
Run python code.
Running Python code requires several steps:
Run the Python initialization code which prepares everything for running the user’s main script. The initialization code can use only the Python built-in modules because the general import mechanism is not yet available. It sets up the Python import mechanism to load modules only from archives embedded in the executable. It also adds the attributes
frozen
and_MEIPASS
to thesys
built-in module.Execute any run-time hooks: first those specified by the user, then any standard ones.
Install python “egg” files. When a module is part of a zip file (.egg), it has been bundled into the
./eggs
directory. Installing means appending .egg file names tosys.path
. Python automatically detects whether an item insys.path
is a zip file or a directory.Run the main script.
Python imports in a bundled app¶
PyInstaller embeds compiled python code
(.pyc
files) within the executable.
PyInstaller injects its code into the
normal Python import mechanism.
Python allows this;
the support is described in PEP 302 “New Import Hooks”.
PyInstaller implements the PEP 302 specification for
importing built-in modules,
importing “frozen” modules (compiled python code
bundled with the app) and for C-extensions.
The code can be read in ./PyInstaller/loader/pyi_mod03_importers.py
.
At runtime the PyInstaller PEP 302 hooks are appended
to the variable sys.meta_path
.
When trying to import modules the interpreter will
first try PEP 302 hooks in sys.meta_path
before searching in sys.path
.
As a result, the Python interpreter
loads imported python modules from the archive embedded
in the bundled executable.
This is the resolution order of import statements in a bundled app:
Is it a built-in module? A list of built-in modules is in variable
sys.builtin_module_names
.Is it a module embedded in the executable? Then load it from embedded archive.
Is it a C-extension? The app will try to find a file with name
package.subpackage.module.pyd
orpackage.subpackage.module.so
.Next examine paths in the
sys.path
. There could be any additional location with python modules or.egg
filenames.If the module was not found then raise
ImportError
.
Splash screen startup¶
Note
This feature is incompatible with macOS. In the current design, the splash screen operates in a secondary thread, which is disallowed by the Tcl/Tk (or rather, the underlying GUI toolkit) on macOS.
If a splash screen is bundled with the application the bootloaders startup procedure and threading model is a little more complex. The following describes the order of operation if a splash screen is bundled:
The bootloader checks if it runs as the outermost application (Not the child process which was spawned by the bootloader).
If splash screen resources are bundled, try to extract them (onefile mode). The extraction path is inside
temppath/_MEIxxxxxx/__splashx
. If in onedir mode, the application assumes the resources are relative to the executable.Load the tcl and tk shared libraries into the bootloader.
Windows:
tcl86t.dll
/tk86t.dll
Linux:
libtcl.so
/libtk.so
Prepare a minimal environment for the Tcl/Tk interpreter by replacing/modifying the following functions:
::tclInit
: This command is called to find the standard library of tcl. We replace this command to force tcl to load/execute only the bundled modules.::tcl_findLibrary
: Tk uses this function to source all its components. The overwritten function sets the required environment variable and evaluates the requested file.::exit
: This function is modified to ensure a proper exit of the splash screen thread.::source
: This command executes the contents of a passed file. Since we run in a minimal environment we mock the execution of not bundled files and execute those who are.
Start the tcl interpreter and execute the splash screen script which was generated by PyInstaller’s build target
Splash
at build time. This script creates the environment variable_PYIBoot_SPLASH
, which is also available to the python interpreter. It also initializes a tcp server socket to receive commands from python.
Note
The tcl interpreter is started in a separate thread. Only after the tcl interpreter has executed the splash screen script, the bootloader thread, which is responsible for extraction/starting the python interpreter, is resumed.
pyi_splash
Module (Detailed)¶
This module connects to the bootloader to send messages to the splash screen.
It is intended to act as an RPC interface for the functions provided by the bootloader, such as displaying text or closing. This makes the users python program independent of how the communication with the bootloader is implemented, since a consistent API is provided.
To connect to the bootloader, it connects to a local tcp server socket whose port
is passed through the environment variable _PYIBoot_SPLASH
. The bootloader
connects to the socket via the python module _socket
. Although this socket
is bidirectional, the module is only configured to send data.
Since the os-module, which is needed to request the environment variable,
is not available at boot time, the module does not establish the connection
until initialization.
This module does not support reloads while the splash screen is displayed, i.e.
it cannot be reloaded (such as by importlib.reload()
), because the splash
screen closes automatically when the connection to this instance of the
module is lost.
Functions¶
Note
Note that if the _PYIBoot_SPLASH
environment variable does not exist or an
error occurs during the connection, the module will not raise an error, but simply
not initialize itself (i.e. pyi_splash.is_alive()
will return False
). Before
sending commands to the splash screen, one should check if the module was initialized
correctly, otherwise a RuntimeError
will be raised.
- is_alive()¶
Indicates whether the module can be used.
Returns
False
if the module is either not initialized ot was disabled by closing the splash screen. Otherwise, the module should be usable.
- update_text(msg)¶
Updates the text on the splash screen window.
- Parameters
msg (str) – the text to be displayed
- Raises
ConnectionError – If the OS fails to write to the socket
RuntimeError – If the module is not initialized
- close()¶
Close the connection to the ipc tcp server socket
This will close the splash screen and renders this module unusable. After this function is called, no connection can be opened to the splash screen again and all functions if this module become unusable
The TOC and Tree Classes¶
PyInstaller manages lists of files using the TOC
(Table Of Contents) class.
It provides the Tree
class as a convenient way to build a TOC
from a folder path.
TOC Class (Table of Contents)¶
Objects of the TOC
class are used as input to the classes created in
a spec file.
For example, the scripts
member of an Analysis object is a TOC
containing a list of scripts.
The pure
member is a TOC with a list of modules, and so on.
Basically a TOC
object contains a list of tuples of the form
(
name,
path,
typecode)
In fact, it acts as an ordered set of tuples; that is, it contains no duplicates (where uniqueness is based on the name element of each tuple). Within this constraint, a TOC preserves the order of tuples added to it.
A TOC behaves like a list and supports the same methods
such as appending, indexing, etc.
A TOC also behaves like a set, and supports taking differences and intersections.
In all of these operations a list of tuples can be used as one argument.
For example, the following expressions are equivalent ways to
add a file to the a.datas
member:
a.datas.append( [ ('README', 'src/README.txt', 'DATA' ) ] )
a.datas += [ ('README', 'src/README.txt', 'DATA' ) ]
Set-difference makes excluding modules quite easy. For example:
a.binaries - [('badmodule', None, None)]
is an expression that produces a new TOC
that is a copy of
a.binaries
from which any tuple named badmodule
has been removed.
The right-hand argument to the subtraction operator
is a list that contains one tuple
in which name is badmodule
and the path and typecode elements
are None
.
Because set membership is based on the name element of a tuple only,
it is not necessary to give accurate path and typecode elements when subtracting.
In order to add files to a TOC, you need to know the typecode values and their related path values. A typecode is a one-word string. PyInstaller uses a number of typecode values internally, but for the normal case you need to know only these:
typecode |
description |
name |
path |
---|---|---|---|
‘DATA’ |
Arbitrary files. |
Run-time name. |
Full path name in build. |
‘BINARY’ |
A shared library. |
Run-time name. |
Full path name in build. |
‘EXTENSION’ |
A binary extension to Python. |
Run-time name. |
Full path name in build. |
‘OPTION’ |
A Python run-time option. |
Option code |
ignored. |
The run-time name of a file will be used in the final bundle.
It may include path elements, for example extras/mydata.txt
.
A BINARY
file or an EXTENSION
file is assumed to be loadable, executable code,
for example a dynamic library.
The types are treated the same.
EXTENSION
is generally used for a Python extension module,
for example a module compiled by Cython.
PyInstaller will examine either type of file for dependencies,
and if any are found, they are also included.
The Tree Class¶
The Tree class is a way of creating a TOC that describes some or all of the files within a directory:
Tree(
root, prefix=
run-time-folder, excludes=
string_list, typecode=
code |'DATA' )
The root argument is a path string to a directory. It may be absolute or relative to the spec file directory.
The prefix argument, if given, is a name for a subfolder within the run-time folder to contain the tree files. If you omit prefix or give
None
, the tree files will be at the top level of the run-time folder.The excludes argument, if given, is a list of one or more strings that match files in the root that should be omitted from the Tree. An item in the list can be either:
a name, which causes files or folders with this basename to be excluded
*.ext
, which causes files with this extension to be excluded
The typecode argument, if given, specifies the TOC typecode string that applies to all items in the Tree. If omitted, the default is
DATA
, which is appropriate for most cases.
For example:
extras_toc = Tree('../src/extras', prefix='extras', excludes=['tmp','*.pyc'])
This creates extras_toc
as a TOC object that lists
all files from the relative path ../src/extras
,
omitting those that have the basename (or are in a folder named) tmp
or that have the type .pyc
.
Each tuple in this TOC has:
A name composed of
extras/filename
.A path consisting of a complete, absolute path to that file in the
../src/extras
folder (relative to the location of the spec file).A typecode of
DATA
(by default).
An example of creating a TOC listing some binary modules:
cython_mods = Tree( '..src/cy_mods', excludes=['*.pyx','*.py','*.pyc'], typecode='EXTENSION' )
This creates a TOC with a tuple for every file in the cy_mods
folder,
excluding any with the .pyx
, .py
or .pyc
suffixes
(so presumably collecting the .pyd
or .so
modules created by Cython).
Each tuple in this TOC has:
Its own filename as name (no prefix; the file will be at the top level of the bundle).
A path as an absolute path to that file in
../src/cy_mods
relative to the spec file.A typecode of
EXTENSION
(BINARY
could be used as well).
Inspecting Archives¶
An archive is a file that contains other files,
for example a .tar
file, a .jar
file, or a .zip
file.
Two kinds of archives are used in PyInstaller.
One is a ZlibArchive, which
allows Python modules to be stored efficiently and,
with some import hooks, imported directly.
The other, a CArchive, is similar to a .zip
file,
a general way of packing up (and optionally compressing) arbitrary blobs of data.
It gets its name from the fact that it can be manipulated easily from C
as well as from Python.
Both of these derive from a common base class, making it fairly easy to
create new kinds of archives.
ZlibArchive¶
A ZlibArchive contains compressed .pyc
or .pyo
files.
The PYZ
class invocation in a spec file creates a ZlibArchive.
The table of contents in a ZlibArchive
is a Python dictionary that associates a key,
which is a member’s name as given in an import
statement,
with a seek position and a length in the ZlibArchive.
All parts of a ZlibArchive are stored in the
marshalled format and so are platform-independent.
A ZlibArchive is used at run-time to import bundled python modules.
Even with maximum compression this works faster than the normal import.
Instead of searching sys.path
, there’s a lookup in the dictionary.
There are no directory operations and no
file to open (the file is already open).
There’s just a seek, a read and a decompress.
A Python error trace will point to the source file from which the archive
entry was created (the __file__
attribute from the time the
.pyc
was compiled, captured and saved in the archive).
This will not tell your user anything useful,
but if they send you a Python error trace,
you can make sense of it.

Structure of the ZlibArchive¶
CArchive¶
A CArchive can contain any kind of file.
It’s very much like a .zip
file.
They are easy to create in Python and easy to unpack from C code.
A CArchive can be appended to another file, such as
an ELF and COFF executable.
To allow this, the archive is made with its table of contents at the
end of the file, followed only by a cookie that tells where the
table of contents starts and
where the archive itself starts.
A CArchive can be embedded within another CArchive. An inner archive can be opened and used in place, without having to extract it.
Each table of contents entry has variable length. The first field in the entry gives the length of the entry. The last field is the name of the corresponding packed file. The name is null terminated. Compression is optional for each member.
There is also a type code associated with each member.
The type codes are used by the self-extracting executables.
If you’re using a CArchive
as a .zip
file, you don’t need to worry about the code.
The ELF executable format (Windows, GNU/Linux and some others) allows arbitrary data to be concatenated to the end of the executable without disturbing its functionality. For this reason, a CArchive’s Table of Contents is at the end of the archive. The executable can open itself as a binary file, seek to the end and ‘open’ the CArchive.

Structure of the CArchive¶

Structure of the Self Extracting Executable¶
Using pyi-archive_viewer¶
Use the pyi-archive_viewer
command to inspect any type of archive:
pyi-archive_viewer
archivefile
With this command you can examine the contents of any archive built with
PyInstaller (a PYZ
or PKG
), or any executable (.exe
file
or an ELF or COFF binary).
The archive can be navigated using these commands:
- O name
Open the embedded archive name (will prompt if omitted). For example when looking in a one-file executable, you can open the
PYZ-00.pyz
archive inside it.- U
Go up one level (back to viewing the containing archive).
- X name
Extract name (will prompt if omitted). Prompts for an output filename. If none given, the member is extracted to stdout.
- Q
Quit.
The pyi-archive_viewer
command has these options:
- -h, --help
Show help.
- -l, --log
Quick contents log.
- -b, --brief
Print a python evaluable list of contents filenames.
- -r, --recursive
Used with -l or -b, applies recursive behaviour.
Inspecting Executables¶
You can inspect any executable file with pyi-bindepend
:
pyi-bindepend
executable_or_dynamic_library
The pyi-bindepend
command analyzes the executable or DLL you name
and writes to stdout all its binary dependencies.
This is handy to find out which DLLs are required by
an executable or by another DLL.
pyi-bindepend
is used by PyInstaller to
follow the chain of dependencies of binary extensions
during Analysis.
Creating a Reproducible Build¶
In certain cases it is important that when you build the same application twice, using exactly the same set of dependencies, the two bundles should be exactly, bit-for-bit identical.
That is not the case normally. Python uses a random hash to make dicts and other hashed types, and this affects compiled byte-code as well as PyInstaller internal data structures. As a result, two builds may not produce bit-for-bit identical results even when all the components of the application bundle are the same and the two applications execute in identical ways.
You can ensure that a build will produce the same bits
by setting the PYTHONHASHSEED
environment variable to a known
integer value before running PyInstaller.
This forces Python to use the same random hash sequence until
PYTHONHASHSEED
is unset or set to 'random'
.
For example, execute PyInstaller in a script such as
the following (for GNU/Linux and OS X):
# set seed to a known repeatable integer value
PYTHONHASHSEED=1
export PYTHONHASHSEED
# create one-file build as myscript
pyinstaller myscript.spec
# make checksum
cksum dist/myscript/myscript | awk '{print $1}' > dist/myscript/checksum.txt
# let Python be unpredictable again
unset PYTHONHASHSEED
Changed in version 4.8: The build timestamp in the PE headers of the generated Windows
executables is set to the current time during the assembly process.
A custom timestamp value can be specified via the SOURCE_DATE_EPOCH
environment variable to achieve reproducible builds.
Understanding PyInstaller Hooks¶
Note
We strongly encourage package developers to provide hooks with their packages. See section Providing PyInstaller Hooks with your Package for how easy this is.
In summary, a “hook” file extends PyInstaller to adapt it to the special needs and methods used by a Python package. The word “hook” is used for two kinds of files. A runtime hook helps the bootloader to launch an app. For more on runtime hooks, see Changing Runtime Behavior. Other hooks run while an app is being analyzed. They help the Analysis phase find needed files.
The majority of Python packages use normal methods of importing their dependencies, and PyInstaller locates all their files without difficulty. But some packages make unusual uses of the Python import mechanism, or make clever changes to the import system at runtime. For this or other reasons, PyInstaller cannot reliably find all the needed files, or may include too many files. A hook can tell about additional source files or data files to import, or files not to import.
A hook file is a Python script, and can use all Python features.
It can also import helper methods from PyInstaller.utils.hooks
and useful variables from PyInstaller.compat
.
These helpers are documented below.
The name of a hook file is hook-full.import.name.py
,
where full.import.name is
the fully-qualified name of an imported script or module.
You can browse through the existing hooks in the
hooks
folder of the PyInstaller distribution folder
and see the names of the packages for which hooks have been written.
For example hook-PyQt5.QtCore.py
is a hook file telling
about hidden imports needed by the module PyQt5.QtCore
.
When your script contains import PyQt5.QtCore
(or from PyQt5 import QtCore
),
Analysis notes that hook-PyQt5.QtCore.py
exists, and will call it.
Many hooks consist of only one statement, an assignment to hiddenimports
.
For example, the hook for the dnspython package, called
hook-dns.rdata.py
, has only this statement:
hiddenimports = [
"dns.rdtypes.*",
"dns.rdtypes.ANY.*"
]
When Analysis sees import dns.rdata
or from dns import rdata
it calls hook-dns.rdata.py
and examines its value
of hiddenimports
.
As a result, it is as if your source script also contained:
import dns.rdtypes.*
import dsn.rdtypes.ANY.*
A hook can also cause the addition of data files, and it can cause certain files to not be imported. Examples of these actions are shown below.
When the module that needs these hidden imports is useful only to your project,
store the hook file(s) somewhere near your source file.
Then specify their location to the pyinstaller
or pyi-makespec
command with the --additional-hooks-dir
option.
If the hook file(s) are at the same level as the script,
the command could be simply:
pyinstaller --additional-hooks-dir=. myscript.py
If you write a hook for a module used by others, please ask the package developer to include the hook with her/his package or send us the hook file so we can make it available.
How a Hook Is Loaded¶
A hook is a module named hook-full.import.name.py
in a folder where the Analysis object looks for hooks.
Each time Analysis detects an import, it looks for a hook file with
a matching name.
When one is found, Analysis imports the hook’s code into a Python namespace.
This results in the execution of all top-level statements in the hook source,
for example import statements, assignments to global names, and
function definitions.
The names defined by these statements are visible to Analysis
as attributes of the namespace.
Thus a hook is a normal Python script and can use all normal Python facilities.
For example it could test sys.version
and adjust its
assignment to hiddenimports
based on that.
There are many hooks in the PyInstaller installation,
but a much larger collection can be found in the
community hooks package.
Please browse through them for examples.
Providing PyInstaller Hooks with your Package¶
As a package developer you can provide hooks for PyInstaller
within your package.
This has the major benefit
that you can easily adopt the hooks
when your package changes.
Thus your package’s users don’t need to wait until PyInstaller
might catch up with these changes.
If both PyInstaller and your package provide hooks for some module,
your package’s hooks take precedence,
but can still be overridden by the command line option
--additional-hooks-dir
.
You can tell PyInstaller about the additional hooks
by defining some simple setuptools entry-points
in your package.
Therefore add entries like these to your setup.cfg
:
[options.entry_points]
pyinstaller40 =
hook-dirs = pyi_hooksample.__pyinstaller:get_hook_dirs
tests = pyi_hooksample.__pyinstaller:get_PyInstaller_tests
This defines two entry-points:
pyinstaller40.hook-dirs
for hook registrationThis entry point refers to a function that will be invoked with no parameters. It must return a sequence of strings, each element of which provides an additional absolute path to search for hooks. This is equivalent to passing the
--additional-hooks-dir
command-line option to PyInstaller for each string in the sequence.In this example, the function is
get_hook_dirs() -> List[str]
.pyinstaller40.tests
for test registrationThis entry point refers to a function that will be invoked with no parameters. It must return a sequence of strings, each element of which provides an additional absolute path to a directory tree or to a Python source file. These paths are then passed to pytest for test discovery. This allows both testing by this package and by PyInstaller.
In this project, the function is
get_PyInstaller_tests() -> List[str]
.
A sample project providing a guide for integrating PyInstaller hooks and tests into a package is available at https://github.com/pyinstaller/hooksample. This project demonstrates defining a library which includes PyInstaller hooks along with tests for those hooks and sample file for integration into CD/CI testing. Detailed documentation about this sample project is available at https://pyinstaller-sample-hook.readthedocs.io/en/latest/.
Hook Global Variables¶
A majority of the existing hooks consist entirely of assignments of values to one or more of the following global variables. If any of these are defined by the hook, Analysis takes their values and applies them to the bundle being created.
hiddenimports
A list of module names (relative or absolute) that should be part of the bundled app. This has the same effect as the
--hidden-import
command line option, but it can contain a list of names and is applied automatically only when the hooked module is imported. Example:hiddenimports = ['_gdbm', 'socket', 'h5py.defs']
excludedimports
A list of absolute module names that should not be part of the bundled app. If an excluded module is imported only by the hooked module or one of its sub-modules, the excluded name and its sub-modules will not be part of the bundle. (If an excluded name is explicitly imported in the source file or some other module, it will be kept.) Several hooks use this to prevent automatic inclusion of the
tkinter
module. Example:excludedimports = ['tkinter']
datas
A list of files to bundle with the app as data. Each entry in the list is a tuple containing two strings. The first string specifies a file (or file “glob”) in this system, and the second specifies the name(s) the file(s) are to have in the bundle. (This is the same format as used for the
datas=
argument, see Adding Data Files.) Example:datas = [ ('/usr/share/icons/education_*.png', 'icons') ]
If you need to collect multiple directories or nested directories, you can use helper functions from the
PyInstaller.utils.hooks
module (see below) to create this list, for example:datas = collect_data_files('submodule1') datas += collect_data_files('submodule2')
In rare cases you may need to apply logic to locate particular files within the file system, for example because the files are in different places on different platforms or under different versions. Then you can write a
hook()
function as described below under The hook(hook_api) Function.binaries
A list of files or directories to bundle as binaries. The format is the same as
datas
(tuples with strings that specify the source and the destination). Binaries is a special case ofdatas
, in that PyInstaller will check each file to see if it depends on other dynamic libraries. Example:binaries = [ ('C:\\Windows\\System32\\*.dll', 'dlls') ]
Many hooks use helpers from the
PyInstaller.utils.hooks
module to create this list (see below):binaries = collect_dynamic_libs('zmq')
Useful Items in PyInstaller.compat
¶
Various classes and functions to provide some backwards-compatibility with previous versions of Python onward.
A hook may import the following names from PyInstaller.compat
,
for example:
from PyInstaller.compat import base_prefix, is_win
- is_py36, is_py37, is_py38, is_py39, is_py310
True when the current version of Python is at least 3.6, 3.7, 3.8, 3.9, or 3.10, respectively.
- is_win¶
True in a Windows system.
- is_cygwin¶
True when
sys.platform == 'cygwin'
.
- is_darwin¶
True in Mac OS X.
- is_linux¶
True in any GNU/Linux system.
- is_solar¶
True in Solaris.
- is_aix¶
True in AIX.
- is_freebsd¶
True in FreeBSD.
- is_openbsd¶
True in OpenBSD.
- is_venv¶
True in any virtual environment (either virtualenv or venv).
- base_prefix¶
String, the correct path to the base Python installation, whether the installation is native or a virtual environment.
- EXTENSION_SUFFIXES¶
List of Python C-extension file suffixes. Used for finding all binary dependencies in a folder; see
hook-cryptography.py
for an example.
Useful Items in PyInstaller.utils.hooks
¶
A hook may import useful functions from PyInstaller.utils.hooks
.
Use a fully-qualified import statement, for example:
from PyInstaller.utils.hooks import collect_data_files, eval_statement
The functions listed here are generally useful and used in a number of existing hooks.
- exec_statement(statement)¶
Execute a single Python statement in an externally-spawned interpreter, and return the resulting standard output as a string.
Examples:
tk_version = exec_statement("from _tkinter import TK_VERSION; print(TK_VERSION)") mpl_data_dir = exec_statement("import matplotlib; print(matplotlib.get_data_path())") datas = [ (mpl_data_dir, "") ]
- eval_statement(statement)¶
Execute a single Python statement in an externally-spawned interpreter, and
eval()
its output (if any).Example:
databases = eval_statement(''' import sqlalchemy.databases print(sqlalchemy.databases.__all__) ''') for db in databases: hiddenimports.append("sqlalchemy.databases." + db)
- is_module_satisfies(requirements, version=None, version_attr='__version__')¶
Test if a PEP 0440 requirement is installed.
- Parameters
requirements (str) – Requirements in pkg_resources.Requirements.parse() format.
version (str) – Optional PEP 0440-compliant version (e.g., 3.14-rc5) to be used _instead_ of the current version of this module. If non-None, this function ignores all setuptools distributions for this module and instead compares this version against the version embedded in the passed requirements. This ignores the module name embedded in the passed requirements, permitting arbitrary versions to be compared in a robust manner. See examples below.
version_attr (str) – Optional name of the version attribute defined by this module, defaulting to __version__. If a setuptools distribution exists for this module (it usually does) _and_ the version parameter is None (it usually is), this parameter is ignored.
- Returns
Boolean result of the desired validation.
- Return type
- Raises
AttributeError – If no setuptools distribution exists for this module _and_ this module defines no attribute whose name is the passed version_attr parameter.
ValueError – If the passed specification does _not_ comply with pkg_resources.Requirements syntax.
Examples
# Assume PIL 2.9.0, Sphinx 1.3.1, and SQLAlchemy 0.6 are all installed. >>> from PyInstaller.utils.hooks import is_module_satisfies >>> is_module_satisfies('sphinx >= 1.3.1') True >>> is_module_satisfies('sqlalchemy != 0.6') False >>> is_module_satisfies('sphinx >= 1.3.1; sqlalchemy != 0.6') False # Compare two arbitrary versions. In this case, the module name "sqlalchemy" is simply ignored. >>> is_module_satisfies('sqlalchemy != 0.6', version='0.5') True # Since the "pillow" project providing PIL publishes its version via the custom "PILLOW_VERSION" attribute # (rather than the standard "__version__" attribute), an attribute name is passed as a fallback to validate PIL # when not installed by setuptools. As PIL is usually installed by setuptools, this optional parameter is # usually ignored. >>> is_module_satisfies('PIL == 2.9.0', version_attr='PILLOW_VERSION') True
See also
pkg_resources.Requirements for the syntax details.
- collect_all(package_name, include_py_files=True, filter_submodules=None, exclude_datas=None, include_datas=None)¶
Collect everything for a given package name.
- Parameters
package_name – An
import
-able package name.include_py_files – Forwarded to
collect_data_files()
.filter_submodules – Forwarded to
collect_submodules()
.exclude_datas – Forwarded to
collect_data_files()
.include_datas – Forwarded to
collect_data_files()
.
- Returns
A
(datas, binaries, hiddenimports)
triplet containing:All data files, raw Python files (if include_py_files), and package metadata folders.
All dynamic libraries as returned by
collect_dynamic_libs()
.All submodules of packagename and its dependencies.
- Return type
Typical use:
datas, binaries, hiddenimports = collect_all('my_module_name')
- collect_submodules(package, filter=<function <lambda>>)¶
List all submodules of a given package.
- Parameters
- Returns
All submodules to be assigned to
hiddenimports
in a hook.
This function is intended to be used by hook scripts, not by main PyInstaller code.
Examples:
# Collect all submodules of Sphinx don't contain the word ``test``. hiddenimports = collect_submodules("Sphinx", filter=lambda name: 'test' not in name)
- is_module_or_submodule(name, mod_or_submod)¶
This helper function is designed for use in the
filter
argument ofcollect_submodules()
, by returningTrue
if the givenname
is a module or a submodule ofmod_or_submod
.Examples
The following excludes
foo.test
andfoo.test.one
but notfoo.testifier
.collect_submodules('foo', lambda name: not is_module_or_submodule(name, 'foo.test'))``
- collect_data_files(package, include_py_files=False, subdir=None, excludes=None, includes=None)¶
This function produces a list of
(source, dest)
non-Python (i.e., data) files that reside inpackage
. Its output can be directly assigned todatas
in a hook script; for example, seehook-sphinx.py
. Parameters:The
package
parameter is a string which names the package.By default, all Python executable files (those ending in
.py
,.pyc
, and so on) will NOT be collected; setting theinclude_py_files
argument toTrue
collects these files as well. This is typically used with Python functions (such as those inpkgutil
) that search a given directory for Python executable files and load them as extensions or plugins.The
subdir
argument gives a subdirectory relative topackage
to search, which is helpful when submodules are imported at run-time from a directory lacking__init__.py
.The
excludes
argument contains a sequence of strings or Paths. These provide a list of globs to exclude from the collected data files; if a directory matches the provided glob, all files it contains will be excluded as well. All elements must be relative paths, which are relative to the provided package’s path (/subdir
if provided).Therefore,
*.txt
will exclude only.txt
files inpackage
‘s path, while**/*.txt
will exclude all.txt
files inpackage
‘s path and all its subdirectories. Likewise,**/__pycache__
will exclude all files contained in any subdirectory named__pycache__
.The
includes
function likeexcludes
, but only include matching paths.excludes
overrideincludes
: a file or directory in both lists will be excluded.
This function does not work on zipped Python eggs.
This function is intended to be used by hook scripts, not by main PyInstaller code.
- collect_dynamic_libs(package, destdir=None)¶
This function produces a list of (source, dest) of dynamic library files that reside in package. Its output can be directly assigned to
binaries
in a hook script. The package parameter must be a string which names the package.- Parameters
destdir – Relative path to ./dist/APPNAME where the libraries should be put.
- get_module_file_attribute(package)¶
Get the absolute path of the module with the passed name.
Since modules cannot be directly imported during analysis, this function spawns a subprocess importing the module and returning the value of its
__file__
attribute.
- get_package_paths(package)¶
Given a package, return the path to packages stored on this machine and also returns the path to this particular package. For example, if pkg.subpkg lives in /abs/path/to/python/libs, then this function returns
(/abs/path/to/python/libs, /abs/path/to/python/libs/pkg/subpkg)
.
- copy_metadata(package_name, recursive=False)¶
Collect distribution metadata so that
pkg_resources.get_distribution()
can find it.This function returns a list to be assigned to the
datas
global variable. This list instructs PyInstaller to copy the metadata for the given package to the frozen application’s data directory.- Parameters
- Returns
This should be assigned to
datas
.- Return type
Examples
>>> from PyInstaller.utils.hooks import copy_metadata >>> copy_metadata('sphinx') [('c:\python27\lib\site-packages\Sphinx-1.3.2.dist-info', 'Sphinx-1.3.2.dist-info')]
Some packages rely on metadata files accessed through the
pkg_resources
module. Normally PyInstaller does not include these metadata files. If a package fails without them, you can use this function in a hook file to easily add them to the frozen bundle. The tuples in the returned list have two strings. The first is the full pathname to a folder in this system. The second is the folder name only. When these tuples are added todatas
, the folder will be bundled at the top level.Changed in version 4.3.1: Prevent
dist-info
metadata folders being renamed toegg-info
which brokepkg_resources.require
with extras (see #3033).Changed in version 4.4.0: Add the recursive option.
- collect_entry_point(name)¶
Collect modules and metadata for all exporters of a given entry point.
- Parameters
name (
str
) – The name of the entry point. Check the documentation for the library that uses the entry point to find its name.- Return type
- Returns
A
(datas, hiddenimports)
pair that should be assigned to thedatas
andhiddenimports
, respectively.
For libraries, such as
pytest
orkeyring
, that rely on plugins to extend their behaviour.Examples
Pytest uses an entry point called
'pytest11'
for its extensions. To collect all those extensions use:datas, hiddenimports = collect_entry_point("pytest11")
These values may be used in a hook or added to the
datas
andhiddenimports
arguments in the.spec
file. See Using Spec Files.New in version 4.3.
- get_homebrew_path(formula='')¶
Return the homebrew path to the requested formula, or the global prefix when called with no argument.
Returns the path as a string or None if not found.
Support for Conda¶
Additional helper methods for working specifically with Anaconda distributions are found at
PyInstaller.utils.hooks.conda_support
which is designed to mimic (albeit loosely) the importlib.metadata package. These functions find and parse the
distribution metadata from json files located in the conda-meta
directory.
New in version 4.2.0.
This module is available only if run inside a Conda environment. Usage of this module should therefore be wrapped in a conditional clause:
from PyInstaller.utils.hooks import is_pure_conda
if is_pure_conda:
from PyInstaller.utils.hooks import conda_support
# Code goes here. e.g.
binaries = conda_support.collect_dynamic_libs("numpy")
...
Packages are all referenced by the distribution name you use to install it, rather than the package name you import
it with. I.e., use distribution("pillow")
instead of distribution("PIL")
or use package_distribution("PIL")
.
- distribution(name)¶
Get distribution information for a given distribution name (i.e., something you would
conda install
).- Return type
- package_distribution(name)¶
Get distribution information for a package (i.e., something you would import).
- Return type
For example, the package
pkg_resources
belongs to the distributionsetuptools
, which contains three packages.>>> package_distribution("pkg_resources") Distribution(name="setuptools", packages=['easy_install', 'pkg_resources', 'setuptools'])
- files(name, dependencies=False, excludes=None)¶
List all files belonging to a distribution.
- Parameters
name (
str
) – The name of the distribution.dependencies – Recursively collect files of dependencies too.
excludes – Distributions to ignore if dependencies is true.
- Return type
- Returns
All filenames belonging to the given distribution.
With
dependencies=False
, this is just a shortcut for:conda_support.distribution(name).files
- requires(name, strip_versions=False)¶
List requirements of a distribution.
- class Distribution(json_path)¶
A bucket class representation of a Conda distribution.
This bucket exports the following attributes:
- Variables
name – The distribution’s name.
version – Its version.
files – All filenames as
PackagePath()
s included with this distribution.dependencies – Names of other distributions that this distribution depends on (with version constraints removed).
packages – Names of importable packages included in this distribution.
This class is not intended to be constructed directly by users. Rather use
distribution()
orpackage_distribution()
to provide one for you.
- class PackagePath(*args)¶
A filename relative to Conda’s root (
sys.prefix
).This class inherits from
pathlib.PurePosixPath
even on non-Posix OSs. To convert to apathlib.Path
pointing to the real file, use thelocate()
method.- locate()¶
Return a path-like object for this path pointing to the file’s true location.
- walk_dependency_tree(initial, excludes=None)¶
Collect a
Distribution
and all direct and indirect dependencies of that distribution.
- collect_dynamic_libs(name, dest='.', dependencies=True, excludes=None)¶
Collect DLLs for distribution name.
- Parameters
- Return type
- Returns
List of DLLs in PyInstaller’s
(source, dest)
format.
This collects libraries only from Conda’s shared
lib
(Unix) orLibrary/bin
(Windows) folders. To collect from inside a distribution’s installation use the regularPyInstaller.utils.hooks.collect_dynamic_libs()
.
The hook(hook_api)
Function¶
In addition to, or instead of, setting global values,
a hook may define a function hook(hook_api)
.
A hook()
function should only be needed if the hook
needs to apply sophisticated logic or to make a complex
search of the source machine.
The Analysis object calls the function and passes it a hook_api
object
which has the following immutable properties:
__name__
:The fully-qualified name of the module that caused the hook to be called, e.g.,
six.moves.tkinter
.__file__
:The absolute path of the module. If it is:
A standard (rather than namespace) package, this is the absolute path of this package’s directory.
A namespace (rather than standard) package, this is the abstract placeholder
-
.A non-package module or C extension, this is the absolute path of the corresponding file.
__path__
:A list of the absolute paths of all directories comprising the module if it is a package, or
None
. Typically the list contains only the absolute path of the package’s directory.co
:Code object compiled from the contents of
__file__
(e.g., via thecompile()
builtin).analysis
:The
Analysis
object that loads the hook.
The hook_api
object also offers the following methods:
add_imports( *names )
:The
names
argument may be a single string or a list of strings giving the fully-qualified name(s) of modules to be imported. This has the same effect as adding the names to thehiddenimports
global.del_imports( *names )
:The
names
argument may be a single string or a list of strings, giving the fully-qualified name(s) of modules that are not to be included if they are imported only by the hooked module. This has the same effect as adding names to theexcludedimports
global.add_datas( tuple_list )
:The
tuple_list
argument has the format used with thedatas
global variable. This call has the effect of adding items to that list.add_binaries( tuple_list )
:The
tuple_list
argument has the format used with thebinaries
global variable. This call has the effect of adding items to that list.
The hook()
function can add, remove or change included files using the
above methods of hook_api
.
Or, it can simply set values in the four global variables, because
these will be examined after hook()
returns.
Hooks may access the user parameters, given in the hooksconfig
argument in
the spec file, by calling get_hook_config()
inside a hook() function.
- get_hook_config(hook_api, module_name, key)¶
Get user settings for hooks.
- Parameters
module_name – The module/package for which the key setting belong to.
key – A key for the config.
- Returns
The value for the config.
None
if not set.
The
get_hook_config
function will lookup settings in theAnalysis.hooksconfig
dict.The hook settings can be added to
.spec
file in the form of:a = Analysis(["my-app.py"], ... hooksconfig = { "gi": { "icons": ["Adwaita"], "themes": ["Adwaita"], "languages": ["en_GB", "zh_CN"], }, }, ... )
The pre_find_module_path( pfmp_api )
Method¶
You may write a hook with the special function pre_find_module_path( pfmp_api )
.
This method is called when the hooked module name is first seen
by Analysis, before it has located the path to that module or package
(hence the name “pre-find-module-path”).
Hooks of this type are only recognized if they are stored in
a sub-folder named pre_find_module_path
in a hooks folder,
either in the distributed hooks folder or an --additional-hooks-dir
folder.
You may have normal hooks as well as hooks of this type for the same module.
For example PyInstaller includes both a hooks/hook-distutils.py
and also a hooks/pre_find_module_path/hook-distutils.py
.
The pfmp_api
object that is passed has the following immutable attribute:
module_name
:A string, the fully-qualified name of the hooked module.
The pfmp_api
object has one mutable attribute, search_dirs
.
This is a list of strings that specify the absolute path, or paths,
that will be searched for the hooked module.
The paths in the list will be searched in sequence.
The pre_find_module_path()
function may replace or change
the contents of pfmp_api.search_dirs
.
Immediately after return from pre_find_module_path()
, the contents
of search_dirs
will be used to find and analyze the module.
For an example of use,
see the file hooks/pre_find_module_path/hook-distutils.py
.
It uses this method to redirect a search for distutils when
PyInstaller is executing in a virtual environment.
The pre_safe_import_module( psim_api )
Method¶
You may write a hook with the special function pre_safe_import_module( psim_api )
.
This method is called after the hooked module has been found,
but before it and everything it recursively imports is added
to the “graph” of imported modules.
Use a pre-safe-import hook in the unusual case where:
The script imports package.dynamic-name
The package exists
however, no module dynamic-name exists at compile time (it will be defined somehow at run time)
You use this type of hook to make dynamically-generated names known to PyInstaller. PyInstaller will not try to locate the dynamic names, fail, and report them as missing. However, if there are normal hooks for these names, they will be called.
Hooks of this type are only recognized if they are stored in a sub-folder
named pre_safe_import_module
in a hooks folder,
either in the distributed hooks folder or an --additional-hooks-dir
folder.
(See the distributed hooks/pre_safe_import_module
folder for examples.)
You may have normal hooks as well as hooks of this type for the same module.
For example the distributed system has both a hooks/hook-gi.repository.GLib.py
and also a hooks/pre_safe_import_module/hook-gi.repository.GLib.py
.
The psim_api
object offers the following attributes,
all of which are immutable (an attempt to change one raises an exception):
module_basename
:String, the unqualified name of the hooked module, for example
text
.module_name
:String, the fully-qualified name of the hooked module, for example
email.mime.text
.module_graph
:The module graph representing all imports processed so far.
parent_package
:If this module is a top-level module of its package,
None
. Otherwise, the graph node that represents the import of the top-level module.
The last two items, module_graph
and parent_package
,
are related to the module-graph, the internal data structure used by
PyInstaller to document all imports.
Normally you do not need to know about the module-graph.
The psim_api
object also offers the following methods:
add_runtime_module( fully_qualified_name )
:Use this method to add an imported module whose name may not appear in the source because it is dynamically defined at run-time. This is useful to make the module known to PyInstaller and avoid misleading warnings. A typical use applies the name from the
psim_api
:psim_api.add_runtime_module( psim_api.module_name )
add_alias_module( real_module_name, alias_module_name )
:real_module_name
is the fully-qualifed name of an existing module, one that has been or could be imported by name (it will be added to the graph if it has not already been imported).alias_module_name
is a name that might be referenced in the source file but should be treated as if it werereal_module_name
. This method ensures that if PyInstaller processes an import ofalias_module_name
it will usereal_module_name
.append_package_path( directory )
:The hook can use this method to add a package path to be searched by PyInstaller, typically an import path that the imported module would add dynamically to the path if the module was executed normally.
directory
is a string, a pathname to add to the__path__
attribute.
Hook Configuration Options¶
As of version 4.4, PyInstaller implements a mechanism for passing configuration options to the hooks. At the time of writing, this feature is supported only in .spec files and has no command-line interface equivalent.
The hook configuration options consist of a dictionary that is passed
to the Analysis
object via the hooksconfig
argument. The keys
of the dictionary represent hook identifiers while the values are
dictionaries of hook-specific keys and values that correspond to
hook settings:
a = Analysis(
["program.py"],
...,
hooksconfig={
"some_hook_id": {
"foo": ["entry1", "entry2"],
"bar": 42,
"enable_x": True,
},
"another_hook_id": {
"baz": "value",
},
},
...,
)
Supported hooks and options¶
This section lists hooks that implement support for configuration options. For each hook (or group of hooks), we provide the hook identifier and the list of supported options.
GObject introspection (gi) hooks¶
The options passed under gi hook identifier control the collection
of GLib/Gtk resources (themes, icons, translations) in various
hooks related to GObject introspection
(i.e., hook-gi.*
).
They are especially useful when freezing Gtk3
-based applications on
linux, as they allow one to limit the amount of themes and icons collected
from the system /usr/share
directory.
Hook identifier: gi
Options
languages
[list of strings]: list of locales (e.g., ˙en_US˙) for which translations should be collected. By default,gi
hooks collect all available translations.
icons
[list of strings]: list of icon themes (e.g., Adwaita) that should be collected. By default,gi
hooks collect all available icon themes.
themes
[list of strings]: list of Gtk themes (e.g., Adwaita) that should be collected. By default,gi
hooks collect all available icon themes.
module-versions
[dict of version strings]: versions of gi modules to use. For example, a key of ‘GtkSource’ and value to ‘4’ will use gtksourceview4.
Example
Collect only Adwaita
theme and icons, limit the collected
translations to British English and Simplified Chinese, and use
version 3.0 of Gtk and version 4 of GtkSource:
a = Analysis(
["my-gtk-app.py"],
...,
hooksconfig={
"gi": {
"icons": ["Adwaita"],
"themes": ["Adwaita"],
"languages": ["en_GB", "zh_CN"],
"module-versions": {
"Gtk": "3.0",
"GtkSource": "4",
},
},
},
...,
)
Note
Currently only the module-versions
configuration is available for GtkSource
.
Adding an option to the hook¶
Implementing support for hook options requires access to hook_api
object, which is available only when hook implements the hook(hook_api)
function (as described here).
The value of a hook’s configuration option can be obtained using the
get_hook_config()
function:
# hook-mypackage.py
from PyInstaller.utils.hooks import get_hook_config
# Processing unrelated to hook options, using global hook values
binaries, datas, hiddenimports = ...
# Collect extra data
def hook(hook_api):
# Boolean option 'collect_extra_data'
if get_hook_config(hook_api, 'mypackage', 'collect_extra_data'):
extra_datas = ... # Collect extra data
hook_api.add_datas(extra_datas)
After implementing option handling in the hook, please add a section documenting it under Supported hooks and options, to inform the users of the option’s availability and the meaning of its value(s).
The above hook example allows the user to toggle the collection of extra
data from mypackage
by setting the corresponding option in their
.spec file:
a = Analysis(
["program-using-mypackage.py"],
...,
hooksconfig={
"mypackage": {
"collect_extra_data": True,
},
},
...,
)
Building the Bootloader¶
PyInstaller comes with pre-compiled bootloaders for some platforms in
the bootloader
folder of the distribution folder.
When there is no pre-compiled bootloader for
the current platform (operating-system and word-size),
the pip setup will attempt to build one.
If there is no precompiled bootloader for your platform, or if you want to modify the bootloader source, you need to build the bootloader. To do this,
Download and install Python, which is required for running waf,
git clone or download the source (see the Download section on the web-site),
cd
into the folder where you cloned or unpacked the source to,cd bootloader
, andmake the bootloader with:
python ./waf all
,test the build by ref:running (parts of) the test-suite <running-the-test-suite>.
This will produce the bootloader executables for your current platform
(of course, for Windows these files will have the .exe
extension):
../PyInstaller/bootloader/OS_ARCH/run
,../PyInstaller/bootloader/OS_ARCH/run_d
,../PyInstaller/bootloader/OS_ARCH/runw
(OS X and Windows only), and../PyInstaller/bootloader/OS_ARCH/runw_d
(OS X and Windows only).
The bootloaders architecture defaults to the machine’s one, but can be changed
using the --target-arch
option – given the appropriate compiler and
development files are installed. E.g. to build a 32-bit bootloader on a 64-bit
machine, run:
python ./waf all --target-arch=32bit
If this reports an error, read the detailed notes that follow, then ask for technical help.
By setting the environment variable PYINSTALLER_COMPILE_BOOTLOADER
the pip setup will attempt to build the bootloader for your platform, even
if it is already present.
Supported platforms are
GNU/Linux (using gcc)
Windows (using Visual C++ (VS2015 or later) or MinGW’s gcc)
Mac OX X (using clang)
Contributed platforms are
AIX (using gcc or xlc)
HP-UX (using gcc or xlc)
Solaris
For more information about cross-building please read on and mind the section about the virtual machines provided in the Vagrantfile.
Building for GNU/Linux¶
Development Tools¶
For building the bootloader you’ll need a development environment. You can run the following to install everything required:
On Debian- or Ubuntu-like systems:
sudo apt-get install build-essential zlib1g-dev
On Fedora, RedHat and derivates:
sudo yum groupinstall "Development Tools" sudo yum install zlib-devel
For other Distributions please consult the distributions documentation.
Now you can build the bootloader as shown above.
Alternatively you may want to use the linux64 build-guest provided by the Vagrantfile (see below).
Building Linux Standard Base (LSB) compliant binaries (optional)¶
By default, the bootloaders on GNU/Linux are ”normal“, non-LSB binaries, which should be fine for all GNU/Linux distributions.
If for some reason you want to build Linux Standard Base (LSB) compliant
binaries 1, you can do so by specifying --lsb
on the waf command line,
as follows:
python ./waf distclean all --lsb
LSB version 4.0 is required for successfully building of bootloader. Please
refer to python ./waf --help
for further options related to LSB building.
- 1
Linux Standard Base (LSB) is a set of open standards that should increase compatibility among GNU/Linux distributions. Unfortunately it is not widely adopted and both Debian and Ubuntu dropped support for LSB in autumn 2015. Thus PyInstaller bootloader are no longer provided as LSB binary.
Cross Building for Different Architectures¶
Bootloaders can be built for other architectures such as ARM or MIPS using Docker. The bootloader/Dockerfile contains the instructions on how to do this. Open it in some flavour of text previewer to see them:
less bootloader/Dockerfile
Building for Mac OS X¶
On Mac OS X please install Xcode, Apple’s suite of tools for developing software for Mac OS X. Instead of installing the full Xcode package, you can also install and use Command Line Tools for Xcode. Installing either will provide the clang compiler.
If the toolchain supports universal2 binaries, the 64-bit bootloaders
are by default built as universal2 fat binaries that support both
x86_64 and arm64 architectures. This requires a recent version
of Xcode (12.2 or later). On older toolchains that lack support for
universal2 binaries, a single-arch x86_64 thin bootloader is
built. This behavior can be controlled by passing --universal2
or
--no-universal2
flags to the waf
build command. Attempting to
use --universal2
flag and a toolchain that lacks support for
universal2 binaries will result in configuration error.
Now you can build the bootloader as shown above.
By default, the build script targets Mac OSX 10.13, which can be overridden by exporting the MACOSX_DEPLOYMENT_TARGET environment variable.
Cross-Building for Mac OS X¶
For cross-compiling for OS X you need the Clang/LLVM compiler, the cctools (ld, lipo, …), and the OSX SDK. Clang/LLVM is a cross compiler by default and is available on nearly every GNU/Linux distribution, so you just need a proper port of the cctools and the OS X SDK.
This is easy to get and needs to be done only once and the result can be transferred to you build-system. The build-system can then be a normal (somewhat current) GNU/Linux system. 2
- 2
Please keep in mind that to avoid problems, the system you are using for the preparation steps should have the same architecture (and possible the same GNU/Linux distribution version) as the build-system.
Preparation: Get SDK and Build-tools¶
For preparing the SDK and building the cctools, we use the very helpful scripts from the OS X Cross toolchain. If you are interested in the details, and what other features OS X Cross offers, please refer to its homepage.
To save you reading the OSXCross’ documentation, we prepared a virtual box
definition that performs all required steps.
If you are interested in the precise commands, please refer to
packages_osxcross_debianoid
, prepare_osxcross_debianiod
, and
build_osxcross
in the Vagrantfile.
Please proceed as follows:
Download Command Line Tools for Xcode 12.2 or later. You will need an Apple ID to search and download the files; if you do not have one already, you can register it for free.
Please make sure that you are complying to the license of the respective package.
Save the downloaded .dmg file to
bootloader/_sdks/osx/Xcode_tools.dmg
.Use the Vagrantfile to automatically build the SDK and tools:
vagrant up build-osxcross && vagrant halt build-osxcross
This should create the file
bootloader/_sdks/osx/osxcross.tar.xz
, which will then be installed on the build-system.If for some reason this fails, try running
vagrant provision build-osxcross
.This virtual machine is no longer used, you may now want to discard it using
vagrant destroy build-osxcross
.
Building the Bootloader¶
Again, simply use the Vagrantfile to automatically build the OS X bootloaders:
export TARGET=OSX # make the Vagrantfile build for OS X
vagrant up linux64 && vagrant halt linux
This should create the bootloaders in
* ../PyInstaller/bootloader/Darwin-*/
.
If for some reason this fails, try running
vagrant provision linux64
.
This virtual machine is no longer used, you may now want to discard it using:
vagrant destroy build-osxcross
If you are finished with the OS X bootloaders, unset TARGET again:
unset TARGET
If you don’t want to use the build-guest provided by the Vagrant file,
perform the following steps
(see build_bootloader_target_osx
in the Vagrantfile):
mkdir -p ~/osxcross
tar -C ~/osxcross --xz -xf /vagrant/sdks/osx/osxcross.tar.xz
PATH=~/osxcross/bin/:$PATH
python ./waf all CC=x86_64-apple-darwin15-clang
python ./waf all CC=i386-apple-darwin15-clang
Building for Windows¶
The pre-compiled bootloader coming with PyInstaller are self-contained static executable that imposes no restrictions on the version of Python being used.
When building the bootloader yourself, you have to carefully choose between three options:
Using the Visual Studio C++ compiler.
This allows creating self-contained static executables, which can be used for all versions of Python. This is why the bootloaders delivered with PyInstaller are build using Visual Studio C++ compiler.
Visual Studio 2015 or later is required.
Using the MinGW-w64 suite.
This allows to create smaller, dynamically linked executables, but requires to use the same level of Visual Studio 3 as was used to compile Python. So this bootloader will be tied to a specific version of Python.
The reason for this is, that unlike Unix-like systems, Windows doesn’t supply a system standard C library, leaving this to the compiler. But Mingw-w64 doesn’t have a standard C library. Instead it links against msvcrt.dll, which happens to exist on many Windows installations – but is not guaranteed to exist.
- 3
This description seems to be technically incorrect. I ought to depend on the C++ run-time library. If you know details, please open an issue.
Using cygwin and MinGW.
This will create executables for cygwin, not for ‘plain’ Windows.
In all cases you may want
to set the path to include python, e.g.
set PATH=%PATH%;c:\python35
,to peek into the Vagrantfile or
../appveyor.yml
to learn how we are building.
You can also build the bootloaders for cygwin.
Build using Visual Studio C++¶
With our wscript file, you don’t need to run
vcvarsall.bat
to ’switch’ the environment between VC++ installations and target architecture. The actual version of C++ does not matter and the target architecture is selected by using the--target-arch=
option.If you are not using Visual Studio for other work, installing only the standalone C++ build-tools might be the best option as it avoids bloating your system with stuff you don’t need (and saves a lot if installation time).
Hint
We recommend installing the build-tools software using the chocolatey package manager. While at a first glance it looks like overdose, this is the easiest way to install the C++ build-tools. It comes down to two lines in an administrative powershell:
… one-line-install as written on the chocolatey homepage choco install -y python3 visualstudio2019-workload-vctools
Useful Links:
After installing the C++ build-tool you can build the bootloader as shown above.
Build using MinGW-w64¶
Please be aware of the restrictions mentioned above.
If Visual Studio is not convenient, you can download and install the MinGW distribution from one of the following locations:
Note: Please mind that using cygwin’s python or MinGW
when running ./waf
will
create executables for cygwin, not for Windows.
On Windows, when using MinGW-w64, add PATH_TO_MINGWbin
to your system PATH
. variable. Before building the
bootloader run for example:
set PATH=C:\MinGW\bin;%PATH%
Now you can build the bootloader as shown above.
If you have installed both Visual C++ and MinGW,
you might need to add run python ./waf --gcc all
.
Build using cygwin and MinGW¶
Please be aware that this will create executables for cygwin, not for ‘plain’ Windows.
Use cygwin’s setup.exe
to install python and mingw.
Now you can build the bootloader as shown above.
Building for AIX¶
By default AIX builds 32-bit executables.
For 64-bit executables set the environment variable
OBJECT_MODE
.
If Python was built as a 64-bit executable
then the AIX utilities that work with binary files
(e.g., .o, and .a) may need the flag -X64
.
Rather than provide this flag with every command,
the preferred way to provide this setting
is to use the environment variable OBJECT_MODE
.
Depending on whether Python was build as a 32-bit or a 64-bit executable
you may need to set or unset
the environment variable OBJECT_MODE
.
To determine the size the following command can be used:
$ python -c "import sys; print(sys.maxsize <= 2**32)"
True
When the answer is True
(as above) Python was build as a 32-bit
executable.
When working with a 32-bit Python executable proceed as follows:
unset OBJECT_MODE
./waf configure all
When working with a 64-bit Python executable proceed as follows:
export OBJECT_MODE=64
./waf configure all
Note
The correct setting of OBJECT_MODE
is also needed when you
use PyInstaller to package your application.
To build the bootloader you will need a compiler compatible (identical) with the one used to build python.
Note
Python compiled with a different version of gcc that you are using might not be compatible enough. GNU tools are not always binary compatible.
If you do not know which compiler that was, this command can help you determine if the compiler was gcc or an IBM compiler:
python -c "import sysconfig; print(sysconfig.get_config_var('CC'))"
If the compiler is gcc you may need additional RPMs installed to support the GNU run-time dependencies.
When the IBM compiler is used no additional prerequisites are expected.
The recommended value for CC
with the IBM compilers is
:command:xlc_r.
Building for FreeBSD¶
A FreeBSD bootloader may be built with clang using the usual steps on a FreeBSD machine. Beware, however that any executable compiled natively on FreeBSD will only run on equal or newer versions of FreeBSD. In order to support older versions of FreeBSD, you must compile the oldest OS version you wish to support.
Alternatively, the FreeBSD bootloaders may be cross compiled from Linux using Docker and a FreeBSD cross compiler image. This image is kept in sync with the oldest non end of life FreeBSD release so that anything compiled on it will work on all active FreeBSD versions.
In a random directory:
Start the docker daemon (usually with
systemctl start docker
- possibly requiringsudo
if you haven’t setup rootless docker).Download the latest cross compiler
.tar.xz
image from here.Import the image:
docker image load -i freebsd-cross-build.tar.xz
. The cross compiler image is now saved under the namefreebsd-cross-build
. You may discard the.tar.xz
file if you wish.
Then from the root of this repository:
Run:
docker run -v $(pwd):/io -it freebsd-cross-build bash -c "cd /io/bootloader; ./waf all"
Vagrantfile Virtual Machines¶
PyInstaller maintains a set of virtual machine description for testing and (cross-) building. For managing these boxes, we use vagrant.
All guests 4 will automatically build the bootloader when running vagrant up GUEST or vagrant provision GUEST. They will build both 32- and 64-bit bootloaders.
- 4
Except of guest osxcross, which will build the OS X SDK and cctools as described in section Cross-Building for Mac OS X.
When building the bootloaders, the guests are sharing
the PyInstaller distribution folder and will put the built executables onto
the build-host (into ../PyInstaller/bootloader/
).
Most boxes requires two Vagrant plugins to be installed:
vagrant plugin install vagrant-reload vagrant-scp
Example usage:
vagrant up linux64 # will also build the bootloader
vagrant halt linux64 # or `destroy`
# verify the bootloader has been rebuild
git status ../PyInstaller/bootloader/
You can pass some parameters for configuring the Vagrantfile by setting environment variables, like this:
GUI=1 TARGET=OSX vagrant up linux64
or like this:
export TARGET=OSX
vagrant provision linux64
We currently provide this guests:
- linux64
GNU/Linux (some recent version) used to build the GNU/Linux bootloaders.
If
TARGET=OSX
is set, cross-builds the bootloaders for OS X (see Cross-Building for Mac OS X).If
TARGET=WINDOWS
is set, cross-builds the bootloaders for Windows using mingw. Please have in mind that this imposes the restrictions mentioned above.Otherwise (which is the default) bootloaders for GNU/Linux are build.
- windows10
Windows 10, used for building the Windows bootloaders using Visual C++.
If
MINGW=1
is set, the bootloaders will be build using MinGW. Please be aware of the restrictions mentioned above.
Note
The Windows box uses password authentication, so in some cases you need to enter the password (which is Passw0rd!).
- build-osxcross
GNU/Linux guest used to build the OS X SDK and cctools as described in section Cross-Building for Mac OS X.
Changelog for PyInstaller¶
4.9 (2022-02-03)¶
Bugfix¶
Add support for external paths when running
pkgutil.iter_modules
. Add support for multiple search paths topkgutil.iter_modules
. Correctly handlepkgutil.iter_modules
with an empty list. (#6529)Fix finding
libpython3x.so
when Python is installed with pyenv and the python executable is not linked againstlibpython3x.so
. (#6542)Fix handling of symbolic links in the path matching part of the PyInstaller’s
pkgutil.iter_modules
replacement/override. (#6537)
Hooks¶
Add hooks for
PySide6.QtMultimedia
andPyQt6.QtMultimedia
. (#6489)Add hooks for
QtMultimediaWidgets
of all four supported Qt bindings (PySide2
,PySide6
,PyQt5
, andPySide6
). (#6489)Add support for
setuptools 60.7.1
and its vendoring ofjaraco.text
inpkg_resources
. Exit with an error message ifsetuptools 60.7.0
is encountered due to incompatibility with PyInstaller’s loader logic. (#6564)Collect the
QtWaylandClient
-related plugins to enable Wayland support in the frozen applications using any of the four supported Qt bindings (PySide2
,PyQt5
,PySide6
, andPyQt6
). (#6483)Fix the issue with missing
QtMultimediaWidgets
module when usingPySide2.QtMultimedia
orPySide6.QtMultimedia
in combination with PySide’strue_property
feature. (#6489)
4.8 (2022-01-06)¶
Features¶
(Windows) Set the executable’s build time in PE header to the current time. A custom timestamp can be specified via the
SOURCE_DATE_EPOCH
environment variable to allow reproducible builds. (#6469)Add strictly unofficial support for the Termux platform. (#6484)
Replace the dual-process
onedir
mode on Linux and other Unix-like OSes with a single-process implementation. This makesonedir
mode on these OSes comparable to Windows and macOS, where single-processonedir
mode has already been used for a while. (#6407)
Bugfix¶
(macOS) Fix regression in generation of
universal2
executables that caused the generated executable to failcodesign
strict validation. (#6381)(Windows) Fix
onefile
extraction behavior when the run-time temporary directory is set to a drive letter. The application’s temporary directory is now created directly on the specified drive as opposed to the current directory on the specified drive. (#6051)(Windows) Fix compatibility issues with python 3.9.8 from python.org, arising from the lack of embedded manifest in the
python.exe
executable. (#6367)(Windows) Fix stack overflow in pyarmor-protected frozen applications, caused by the executable’s stack being smaller than that of the python interpreter. (#6459)
(Windows) Fix the
python3.dll
shared library not being found and collected when using Python from MS App Store. (#6390)Fix a bug that prevented traceback from uncaught exception to be retrieved and displayed in the windowed bootloader’s error reporting facility (uncaught exception dialog on Windows, syslog on macOS). (#6426)
Fix a crash when a onefile build attempts to overwrite an existing onedir build on macOS or Linux (#6418)
Fix build errors when a linux shared library (.so) file is collected as a binary on macOS. (#6327)
Fix build errors when a Windows DLL/PYD file is collected as a binary on a non-Windows OS. (#6327)
Fix handling of encodings when reading the collected .py source files via
FrozenImporter.get_source()
. (#6143)Fix hook loader function not finding hooks if path has whitespaces. (Re-apply the fix that has been inadvertedly undone during the codebase reformatting.) (#6080)
Windows: Prevent invalid handle errors when an application compiled in
--windowed
mode usessubprocess
without explicitly setting stdin, stdout and stderr to eitherPIPE
orDEVNULL
. (#6364)
Hooks¶
(macOS) Add support for Anaconda-installed
PyQtWebEngine
. (#6373)Add hooks for
PySide6.QtWebEngineWidgets
andPyQt6.QtWebEngineWidgets
. TheQtWebEngine
support in PyInstaller requiresQt6
v6.2.2 or later, so if an earlier version is encountered, we exit with an error instead of producing a defunct build. (#6387)Avoid collecting the whole
QtQml
module and its dependencies in cases when it is not necessary (i.e., the application does not useQtQml
orQtQuick
modules). The unnecessary collection was triggered due to extension modules being linked against thelibQt5Qml
orlibQt6Qml
shared library, and affected pure widget-based applications (PySide2
andPySide6
on Linux) and widget-based applications that useQtWebEngineWidgets
(PySide2
,PySide6
,PyQt5
, andPyQt6
on all OSes). (#6447)Update
numpy
hook for compatibility with version 1.22; the hook cannot excludedistutils
andnumpy.distutils
anymore, as they are required bynumpy.testing
, which is used by some external packages, such asscipy
. (#6474)
Bootloader¶
(Windows) Set the bootloader executable’s stack size to 2 MB to match the stack size of the python interpreter executable. (#6459)
Implement single-process
onedir
mode for Linux and Unix-like OSes as a replacement for previously-used two-process implementation. The new mode usesexec()
withoutfork()
to restart the bootloader executable image within the same process after setting up the environment (i.e., theLD_LIBRARY_PATH
and other environment variables). (#6407)Lock the PKG sideload mode in the bootloader unless the executable has a special signature embedded. (#6470)
When user script terminates with an uncaught exception, ensure that the exception data obtained via
PyErr_Fetch
is normalized by also callingPyErr_NormalizeException
. Otherwise, trying to format the traceback viatraceback.format_exception
fails in some circumstances, and no traceback can be displayed in the windowed bootloader’s error report. (#6426)
4.7 (2021-11-10)¶
Bugfix¶
Fix a bug since v4.6 where certain Unix system directories were incorrectly assumed to exist and resulted in a
FileNotFoundError
. (#6331)
Bootloader¶
(Windows) Explicitly set
NTDDI_VERSION=0x06010000
and_WIN32_WINNT=0x0601
when compiling Windows bootloaders to request Windows 7 feature level for Windows headers. The windowed bootloader requires at least Windows Vista feature level, and some toolchains (e.g., mingw cross-compiler on linux) set too low level by default. (#6338)(Windows) Remove the check for the unused
windres
utility when compiling with MinGW toolchain. (#6339)Replace use of
PyRun_SimpleString
withPyRun_SimpleStringFlags
. (#6332)
4.6 (2021-10-29)¶
Features¶
Add support for Python 3.10. (#5693)
(Windows) Embed the manifest into generated
onedir
executables by default, in order to avoid potential issues when user renames the executable (e.g., the manifest not being found anymore due to activation context caching when user renames the executable and attempts to run it before also renaming the manifest file). The old behavior of generating the external manifest file inonedir
mode can be re-enabled using the--no-embed-manifest
command-line switch, or via theembed_manifest=False
argument toEXE()
in the .spec file. (#6248)(Windows) Respect PEP 239 encoding specifiers in Window’s VSVersionInfo files. (#6259)
Implement basic resource reader for accessing on-filesystem resources (data files) via
importlib.resources
(python >= 3.9) orimportlib_resources
(python <= 3.8). (#5616)Ship precompiled wheels for musl-based Linux distributions (such as Alpine or OpenWRT) on
x86_64
andaarch64
. (#6245)
Bugfix¶
(macOS) Ensure that executable pre-processing and post-processing steps (target arch selection, SDK version adjustment, (re)signing) are applied in the stand-alone PKG mode. (#6251)
(macOS) Robustify the macOS assembly pipeline to work around the issues with the
codesign
utility on macOS 10.13 High Sierra. (#6167)(Windows) Fix collection of
sysconfig
platform-specific data module when using MSYS2/MINGW python. (#6118)(Windows) Fix displayed script name and exception message in the unhandled exception dialog (windowed mode) when bootloader is compiled using the
MinGW-w64
toolchain. (#6199)(Windows) Fix issues in
onedir
frozen applications when the bootloader is compiled using a toolchain that forcibly embeds a default manifest (e.g., theMinGW-w64
toolchain frommsys2
). The issues range from manifest-related options (e.g.,uac-admin
) not working to windowed frozen application not starting at all (with theThe procedure entry point LoadIconMetric could not be located...
error message). (#6196)(Windows) Fix the declared length of strings in the optional embedded product version information resource structure. The declared lengths were twice too long, and resulted in trailing garbage characters when the version information was read using ctypes and winver API. (#6219)
(Windows) Remove the attempt to load the manifest of a
onefile
frozen executable via the activation context, which fails withAn attempt to set the process default activation context failed because the process default activation context was already set.
message that can be observed in debug builds. This approach has been invalid ever since #3746 implemented direct manifest embedding into theonefile
executable. (#6248)(Windows) Suppress missing library warnings for
api-ms-win-core-*
DLLs. (#6201)(Windows) Tolerate reading Windows VSVersionInfo files with unicode byte order marks. (#6259)
Fix
sys.executable
pointing to the external package file instead of the executable when in package side-load mode (pkg_append=False
). (#6202)Fix a runaway glob which caused
ctypes.util.find_library("libfoo")
to non-deterministically pick any library matchinglibfoo*
to bundle instead oflibfoo.so
. (#6245)Fix compatibility with with MIPS and loongarch64 architectures. (#6306)
Fix the
FrozenImporter.get_source()
to correctly handle the packages’__init__.py
source files. This in turn fixes missing-source-file errors for packages that usepytorch
JIT when the source .py files are collected and available (for example,kornia
). (#6237)Fix the location of the generated stand-alone pkg file when using the side-load mode (
pkg_append=False
) in combination withonefile
mode. The package file is now placed next to the executable instead of next to the .spec file. (#6202)When generating spec files, avoid hard-coding the spec file’s location as the
pathex
argument to theAnalysis
. (#6254)
Incompatible Changes¶
(Windows) By default, manifest is now embedded into the executable in
onedir
mode. The old behavior of generating the external manifest file can be re-enabled using the--no-embed-manifest
command-line switch, or via theembed_manifest=False
argument toEXE()
in the .spec file. (#6248)
Hooks¶
(macOS) Fix compatibility with Anaconda
PyQt5
package. (#6181)Add a hook for
pandas.plotting
to restore compatibility withpandas
1.3.0 and later. (#5994)Add a hook for
QtOpenGLWidgets
forPyQt6
andPySide6
to collect the newQtOpenGLWidgets
module introduced in Qt6 (#6310)Add hooks for
QtPositioning
andQtLocation
modules of the Qt5-based packages (PySide2
andPyQt5
) to ensure that corresponding plugins are collected. (#6250)Fix compatibility with
PyQt5
5.9.2 from conda’s main channel. (#6114)Prevent potential error in hooks for Qt-based packages that could be triggered by a partial
PyQt6
installation. (#6141)Update
QtNetwork
hook forPyQt6
andPySide6
to collect the newtls
plugins that were introduced in Qt 6.2. (#6276)Update the
gi.repository.GtkSource
hook to accept a module-versions hooksconfig dict in order to allow the hook to be used with GtkSource versions greater than 3.0. (#6267)
Bootloader¶
(Windows) Suppress two
snprintf
truncation warnings that prevented bootloader from building withwinlibs MinGW-w64
toolchain. (#6196)Update the Linux bootloader cross compiler Dockerfile to allow using the official PyPA base images in place of the dockcross ones. (#6245)
4.5.1 (2021-08-06)¶
4.5 (2021-08-01)¶
Features¶
(POSIX) Add
exclude_system_libraries
function to the Analysis class for .spec files, to exclude most or all non-Python system libraries from the bundle. Documented in new POSIX Specific Options section. (#6022)
Bugfix¶
(Cygwin) Add
_MEIPASS
to DLL search path to fix loading of python shared library in onefile builds made in cygwin environment and executed outside of it. (#6000)(Linux) Display missing library warnings for “not found” lines in
ldd
output (i.e.,libsomething.so => not found
) instead of quietly ignoring them. (#6015)(Linux) Fix spurious missing library warning when
libc.so
points toldd
. (#6015)(macOS) Fix python shared library detection for non-framework python builds when the library path cannot be inferred from imports of the
python
executable. (#6021)(macOS) Fix the crashes in
onedir
bundles oftkinter
-based applications created using Homebrew python 3.9 and Tcl/Tk 8.6.11. (#6043)(macOS) When fixing executable for codesigning, update the value of
vmsize
field in the__LINKEDIT
segment. (#6039)Downgrade messages about missing dynamic link libraries from ERROR to WARNING. (#6015)
Fix a bytecode parsing bug which caused tuple index errors whilst scanning modules which use
ctypes
. (#6007)Fix an error when rhtooks for
pkgutil
andpkg_resources
are used together. (#6018)Fix architecture detection on Apple M1 (#6029)
Fix crash in windowed bootloader when the traceback for unhandled exception cannot be retrieved. (#6070)
Improve handling of errors when loading hook entry-points. (#6028)
Suppress missing library warning for
shiboken2
(PySide2
) andshiboken6
(PySide6
) shared library. (#6015)
Incompatible Changes¶
(macOS) Disable processing of Apple events for the purpose of argv emulation in
onedir
application bundles. This functionality was introduced in PyInstaller 4.4 by (#5920) in response to feature requests (#5436) and (#5908), but was discovered to be breakingtkinter
-basedonedir
bundles made with Homebrew python 3.9 and Tcl/Tk 8.6.11 (#6043). As such, until the cause is investigated and the issue addressed, this feature is reverted/disabled. (#6048)
Hooks¶
Documentation¶
Add a page describing hook configuration mechanism and the currently implemented options. (#6025)
4.4 (2021-07-13)¶
Features¶
(macOS) Implement signing of .app bundle (ad-hoc or with actual signing identity, if provided). (#5581)
(macOS) Implement support for Apple Silicon M1 (
arm64
) platform and different targets for frozen applications (thin-binaryx86_64
, thin-binaryarm64
, and fat-binaryuniversal2
), with build-time arch validation and ad-hoc resigning of all collected binaries. (#5581)(macOS) In
onedir
windowed
(.app bundle) mode, perform an interation of Apple event processing to convertodoc
andGURL
events tosys.argv
before entering frozen python script. (#5920)(macOS) In windowed (.app bundle) mode, always log unhandled exception information to
syslog
, regardless of debug mode. (#5890)(Windows) Add support for Python from Microsoft App Store. (#5816)
(Windows) Implement a custom dialog for displaying information about unhandled exception and its traceback when running in windowed/noconsole mode. (#5890)
Add recursive option to
PyInstaller.utils.hooks.copy_metadata()
. (#5830)Add
--codesign-identity
command-line switch to perform code-signing with actual signing identity instead of ad-hoc signing (macOS only). (#5581)Add
--osx-entitlements-file
command-line switch that specifies optional entitlements file to be used during code signing of collected binaries (macOS only). (#5581)Add
--target-arch
command-line switch to select target architecture for frozen application (macOS only). (#5581)Add a splash screen that displays a background image and text: The splash screen can be controlled from within Python using the
pyi_splash
module. A splash screen can be added using the--splash IMAGE_FILE
option. If optional text is enabled, the splash screen will show the progress of unpacking in onefile mode. This feature is supported only on Windows and Linux. A huge thanks to @Chrisg2000 for programming this feature. (#4354, #4887)Add hooks for
PyQt6
. (#5865)Add hooks for
PySide6
. (#5865)Add option to opt-out from reporting full traceback for unhandled exceptions in windowed mode (Windows and macOS only), via
--disable-windowed-traceback
PyInstaller CLI switch and the correspondingdisable_windowed_traceback
boolean argument toEXE()
in spec file. (#5890)Allow specify which icon set, themes and locales to pack with Gtk applications. Pass a keyword arg
hooksconfig
to Analysis.a = Analysis(["my-gtk-app.py"], ..., hooksconfig={ "gi": { "icons": ["Adwaita"], "themes": ["Adwaita"], "languages": ["en_GB", "zh_CN"] } }, ...)
(#5853)
Automatically exclude Qt plugins from UPX processing. (#4178)
Collect distribution metadata automatically. This works by scanning collected Python files for uses of:
pkg_resources.get_distribution()
pkg_resources.require()
importlib.metadata.distribution()
importlib.metadata.metadata()
importlib.metadata.files()
importlib.metadata.version()
In all cases, the metadata will only be collected if the distribution name is given as a plain string literal. Anything more complex will still require a hook containing
PyInstaller.utils.hooks.copy_metadata()
. (#5830)Implement support for
pkgutil.iter_modules()
. (#1905)Windows: Provide a meaningful error message if given an icon in an unsupported Image format. (#5755)
Bugfix¶
(macOS) App bundles built in
onedir
mode now filter out-psnxxx
command-line argument fromsys.argv
, to keep behavior consistent with bundles built inonefile
mode. (#5920)(macOS) Ensure that the macOS SDK version reported by the frozen application corresponds to the minimum of the SDK version used to build the bootloader and the SDK version used to build the Python library. Having the application report more recent version than Python library and other bundled libraries may result in macOS attempting to enable additional features that are not available in the Python library, which may in turn cause inconsistent behavior and UI issues with
tkinter
. (#5839)(macOS) Remove spurious
MacOS/
prefix fromCFBundleExecutable
property in the generatedInfo.plist
when building an app bundle. (#4413, #5442)(macOS) The drag & drop file paths passed to app bundles built in
onedir
mode are now reflected insys.argv
. (#5436)(macOS) The file paths passed from the UI (Open with…) to app bundles built in
onedir
mode are now reflected insys.argv
. (#5908)(macOS) Work around the
tkinter
UI issues due to problems with dark mode activation: blackTk
window with macOS Intel installers frompython.org
, or white text on bright background with Anaconda python. (#5827)(Windows) Enable collection of additional VC runtime DLLs (
msvcp140.dll
,msvcp140_1.dll
,msvcp140_2.dll
, andvcruntime140_1.dll
), to allow frozen applications to run on Windows systems that do not have Visual Studio 2015/2017/2019 Redistributable installed. (#5770)Enable retrieval of code object for
__main__
module via its associated loader (i.e.,FrozenImporter
). (#5897)Fix
inspect.getmodule()
failing to resolve module from stack-frame obtained viainspect.stack()
. (#5963)Fix
__main__
module being recognized as built-in instead of module. (#5897)Fix a bug in ctypes dependency scanning which caused references to be missed if the preceding code contains more than 256 names or 256 literals. (#5830)
Fix collection of duplicated
_struct
andzlib
extension modules with mangled filenames. (#5851)Fix python library lookup when building with RH SCL python 3.8 or later. (#5749)
Prevent
PyInstaller.utils.hooks.copy_metadata()
from renaming[...].dist-info
metadata folders to[...].egg-info
which breaks usage ofpkg_resources.requires()
with extras. (#5774)Prevent a bootloader executable without an embedded CArchive from being misidentified as having one, which leads to undefined behavior in frozen applications with side-loaded CArchive packages. (#5762)
Prevent the use of
sys
oros
as variables in the global namespace in frozen script from affecting thectypes
hooks thar are installed during bootstrap. (#5797)Windows: Fix EXE being rebuilt when there are no changes. (#5921)
Hooks¶
Add
PostGraphAPI.analysis
attribute. Hooks can access theAnalysis
object through thehook()
function.Hooks may access a
Analysis.hooksconfig
attribute assigned onAnalysis
construction.A helper function
get_hook_config()
was defined inutils.hooks
to get the config. (#5853)
Add support for
PyQt5
5.15.4. (#5631)Do not exclude
setuptools.py27compat
andsetuptools.py33compat
as they are required by othersetuptools
modules. (#5979)Switch the library search order in
ctypes
hooks: first check whether the given name exists as-is, before trying to search for its basename insys._MEIPASS
(instead of the other way around). (#5907)
Bootloader¶
(macOS) Build bootloader as
universal2
binary by default (can be disabled by passing--no-universal2
to waf). (#5581)Add Tcl/Tk based Splash screen, which is controlled from within Python. The necessary module to create the Splash screen in PyInstaller is under
Splash
available. A huge thanks to @Chrisg2000 for programming this feature. (#4887)Provide a Dockerfile to build Linux bootloaders for different architectures. (#5995)
4.3 (2021-04-16)¶
Features¶
Provide basic implementation for
FrozenImporter.get_source()
that allows reading source from.py
files that are collected by hooks as data files. (#5697)Raise the maximum allowed size of
CArchive
(and consequentlyonefile
executables) from 2 GiB to 4 GiB. (#3939)The unbuffered stdio mode (the
u
option) now sets thePy_UnbufferedStdioFlag
flag to enable unbuffered stdio mode in Python library. (#1441)Windows: Set EXE checksums. Reduces false-positive detection from antiviral software. (#5579)
Add new command-line options that map to collect functions from hookutils:
--collect-submodules
,--collect-data
,--collect-binaries
,--collect-all
, and--copy-metadata
. (#5391)Add new hook utility
collect_entry_point()
for collecting plugins defined through setuptools entry points. (#5734)
Bugfix¶
(macOS) Fix
Bad CPU type in executable
error in helper-spawned python processes when running underarm64
-only flavor of Python on Apple M1. (#5640)(OSX) Suppress missing library error messages for system libraries as those are never collected by PyInstaller and starting with Big Sur, they are hidden by the OS. (#5107)
(Windows) Change default cache directory to
LOCALAPPDATA
(from the originalAPPDATA
). This is to make sure that cached data doesn’t get synced with the roaming profile. For this and future versionsAppData\Roaming\pyinstaller
might be safely deleted. (#5537)(Windows) Fix
onefile
builds not having manifest embedded when icon is disabled via--icon NONE
. (#5625)(Windows) Fix the frozen program crashing immediately with
Failed to execute script pyiboot01_bootstrap
message when built innoconsole
mode and with import logging enabled (either via--debug imports
or--debug all
command-line switch). (#4213)CArchiveReader
now performs full back-to-front file search forMAGIC
, allowingpyi-archive_viewer
to open binaries with extra appended data after embedded package (e.g., digital signature). (#2372)Fix
MERGE()
to properly set references to nested resources with their full shared-package-relative path instead of just basename. (#5606)Fix
onefile
builds failing to extract files when the full target path exceeds 260 characters. (#5617)Fix a crash in
pyi-archive_viewer
when quitting the application or moving up a level. (#5554)Fix extraction of nested files in
onefile
builds created in MSYS environments. (#5569)Fix installation issues stemming from unicode characters in file paths. (#5678)
Fix the build-time error under python 3.7 and earlier when
ctypes
is manually added tohiddenimports
. (#3825)Fix the return code if the frozen script fails due to unhandled exception. The return code 1 is used instead of -1, to keep the behavior consistent with that of the python interpreter. (#5480)
Linux: Fix binary dependency scanner to support changes to ldconfig introduced in
glibc
2.33. (#5540)Prevent
MERGE
(multipackage) from creating self-references for duplicated TOC entries. (#5652)PyInstaller-frozen onefile programs are now compatible with
staticx
even if the bootloader is built as position-independent executable (PIE). (#5330)Remove dependence on a private function removed in
matplotlib
3.4.0rc1. (#5568)Strip absolute paths from
.pyc
modules collected intobase_library.zip
to enable reproducible builds that are invariant to Python install location. (#5563)(OSX) Fix issues with
pycryptodomex
on macOS. (#5583)Allow compiled modules to be collected into
base_library.zip
. (#5730)Fix a build error triggered by scanning
ctypes.CDLL('libc.so')
on certain Linux C compiler combinations. (#5734)Improve performance and reduce stack usage of module scanning. (#5698)
Hooks¶
Add support for Conda Forge’s distribution of
NumPy
. (#5168)Add support for package content listing via
pkg_resources
. The implementation enables querying/listing resources in a frozen package (both PYZ-embedded and on-filesystem, in that order of precedence) viapkg_resources.resource_exists()
,resource_isdir()
, andresource_listdir()
. (#5284)Hooks: Import correct typelib for GtkosxApplication. (#5475)
Prevent
matplotlib
hook from collecting current working directory when it fails to determine the path to matplotlib’s data directory. (#5629)Update
pandas
hook for compatibility with version 1.2.0 and later. (#5630)Update hook for
distutils.sysconfig
to be compatible with pyenv-virtualenv. (#5218)Update hook for
sqlalchemy
to support version 1.4.0 and above. (#5679)Update hook for
sysconfig
to be compatible with pyenv-virtualenv. (#5018)
Bootloader¶
Implement full back-to-front file search for the embedded archive. (#5511)
Perform file extraction from the embedded archive in a streaming manner in order to limit memory footprint when archive contains large files. (#5551)
Set the
__file__
attribute in the__main__
module (entry-point script) to the absolute file name inside the_MEIPASS
. (#5649)Enable cross compiling for FreeBSD from Linux. (#5733)
Documentation¶
PyInstaller Core¶
Drop support for python 3.5; EOL since September 2020. (#5439)
Collect python extension modules that correspond to built-ins into
lib-dynload
sub-directory instead of directly into bundle’s root directory. This prevents them from shadowing shared libraries with the same basename that are located in a package and loaded viactypes
orcffi
, and also declutters the bundle’s root directory. (#5604)
Breaking¶
No longer collect
pyconfig.h
andmakefile
forsysconfig
. Instead ofget_config_h_filename()
andget_makefile_filename()
, you should useget_config_vars()
which no longer depends on those files. (#5218)The
__file__
attribute in the__main__
module (entry-point script) is now set to the absolute file name inside the_MEIPASS
(as if script file existed there) instead of just script filename. This better matches the behavior of__file__
in the unfrozen script, but might break the existing code that explicitly relies on the old frozen behavior. (#5649)
4.2 (2021-01-13)¶
Features¶
Add hooks utilities to find binary dependencies of Anaconda distributions. (#5213)
(OSX) Automatically remove the signature from the collected copy of the
Python
shared library, usingcodesign --remove-signature
. This accommodates bothonedir
andonefile
builds with recent python versions for macOS, where invalidated signature on PyInstaller-collected copy of thePython
library prevents the latter from being loaded. (#5451)(Windows) PyInstaller’s console or windowed icon is now added at freeze-time and no longer built into the bootloader. Also, using
--icon=NONE
allows to not apply any icon, thereby making the OS to show some default icon. (#4700)(Windows) Enable
longPathAware
option in built application’s manifest in order to support long file paths on Windows 10 v.1607 and later. (#5424)
Bugfix¶
Fix loading of plugin-type modules at run-time of the frozen application: If the plugin path is one character longer than sys._MEIPATH (e.g. “$PWD/p/plugin_1” and “$PWD/dist/main”), the plugin relative-imports a sub-module (of the plugin) and the frozen application contains a module of the same name, the frozen application module was imported. (#4141, #4299)
Ensure that spec for frozen packages has
submodule_search_locations
set in order to fix compatibility withimportlib_resources
3.2.0 and later. (#5396)Fix: No rebuild if “noarchive” build-option changes. (#5404)
(OSX) Fix the problem with
Python
shared library collected from recent python versions not being loaded due to invalidated signature. (#5062, #5272, #5434)(Windows) PyInstaller’s default icon is no longer built into the bootloader, but added at freeze-time. Thus, when specifiying an icon, only that icon is contained in the executable and displayed for a shortcut. (#870, #2995)
(Windows) Fix “toc is bad” error messages when passing a
VSVersionInfo
as theversion
parameter toEXE()
in a.spec
file. (#5445)(Windows) Fix exception when trying to read a manifest from an exe or dll. (#5403)
(Windows) Fix the
--runtime-tmpdir
option by creating paths if they don’t exist and expanding environment variables (e.g.%LOCALAPPDATA%
). (#3301, #4579, #4720)
Hooks¶
(GNU/Linux) Collect
xcbglintegrations
andegldeviceintegrations
plugins as part ofQt5Gui
. (#5349)(macOS) Fix: Unable to code sign apps built with GTK (#5435)
(Windows) Add a hook for
win32ctypes.core
. (#5250)Add hook for
scipy.spatial.transform.rotation
to fix compatibility with SciPy 1.6.0. (#5456)Add hook-gi.repository.GtkosxApplication to fix TypeError with Gtk macOS apps. (#5385)
Add hooks utilities to find binary dependencies of Anaconda distributions. (#5213)
Fix the
Qt5
library availability check inPyQt5
andPySide2
hooks to re-enable support forQt5
older than 5.8. (#5425)Implement
exec_statement_rc()
andexec_script_rc()
as exit-code returning counterparts ofexec_statement()
andexec_script()
. Implementcan_import_module()
helper for hooks that need to query module availability. (#5301)Limit the impact of a failed sub-package import on the result of
collect_submodules()
to ensure that modules from all other sub-packages are collected. (#5426)Removed obsolete
pygame
hook. (#5362)Update
keyring
hook to collect metadata, which is required for backend discovery. (#5245)
Bootloader¶
(GNU/Linux) Reintroduce executable resolution via
readlink()
on/proc/self/exe
and preserve the process name usingprctl()
withPR_GET_NAME
andPR_SET_NAME
. (#5232)(Windows) Create temporary directories with user’s SID instead of
S-1-3-4
, to work around the lack of support for the latter inwine
. This enablesonefile
builds to run underwine
again. (#5216)(Windows) Fix a bug in path-handling code with paths exceeding
PATH_MAX
, which is caused by use of_snprintf
instead ofsnprintf
when building with MSC. Requires Visual Studio 2015 or later. Clean up the MSC codepath to address other compiler warnings. (#5320)(Windows) Fix building of bootloader’s test suite under Windows with Visual Studio. This fixes build errors when
cmocka
is present in the build environment. (#5318)(Windows) Fix compiler warnings produced by MinGW 10.2 in order to allow building the bootloader without having to suppress the warnings. (#5322)
(Windows) Fix
windowed+debug
bootloader variant not properly displaying the exception message and traceback information when the frozen script terminates due to uncaught exception. (#5446)
PyInstaller Core¶
(Windows) Avoid using UPX with DLLs that have control flow guard (CFG) enabled. (#5382)
Avoid using
.pyo
module file suffix (removed since PEP-488) innoarchive
mode. (#5383)Improve support for
PEP-420
namespace packages. (#5354)Strip absolute paths from
.pyc
modules collected in the CArchive (PKG). This enables build reproducibility without having to match the location of the build environment. (#5380)
4.1 (2020-11-18)¶
Bugfix¶
Hooks¶
Add
exclude_datas
,include_datas
, andfilter_submodules
tocollect_all()
. These arguments map to theexcludes
andincludes
arguments ofcollect_data_files
, and to the filter argument ofcollect_submodules
. (#5113)Add hook for difflib to not pull in doctests, which is only required when run as main programm.
Add hook for distutils.util to not pull in lib2to3 unittests, which will be rearly used in frozen packages.
Add hook for heapq to not pull in doctests, which is only required when run as main programm.
Add hook for multiprocessing.util to not pull in python test-suite and thus e.g. tkinter.
Add hook for numpy._pytesttester to not pull in pytest.
Add hook for pickle to not pull in doctests and argpargs, which are only required when run as main programm.
Add hook for PIL.ImageFilter to not pull numpy, which is an optional component.
Add hook for setuptools to not pull in numpy, which is only imported if installed, not mean to be a dependency
Add hook for zope.interface to not pull in pytest unittests, which will be rearly used in frozen packages.
Add hook-gi.repository.HarfBuzz to fix Typelib error with Gtk apps. (#5133)
Enable overriding Django settings path by DJANGO_SETTINGS_MODULE environment variable. (#5267)
Fix collect_system_data_files to scan the given input path instead of its parent. File paths returned by collect_all_system_data are now relative to the input path. (#5110)
Fix argument order in
exec_script()
andeval_script()
. (#5300)Gevent hook does not unnecessarily bundle HTML documentation, __pycache__ folders, tests nor generated .c and .h files (#4857)
gevent: Do not pull in test-suite (still to be refined)
Modify hook for
gevent
to exclude test submodules. (#5201)Prevent .pyo files from being collected by collect_data_files when include_py_files is False. (#5141)
Prevent output to
stdout
during module imports from ending up in the modules list collected bycollect_submodules
. (#5244)Remove runtime hook and fix regular hook for matplotlib’s data to support
matplotlib>=3.3.0
, fix deprecation warning on version 3.1<= & <3.3, and behave normally for versions <3.1. (#5006)Remove support for deprecated PyQt4 and PySide (#5118, #5126)
setuptools: Exclude outdated compat modules.
Update
sqlalchemy
hook to support v1.3.19 and later, by addingsqlalchemy.ext.baked
as a hidden import (#5128)Update
tkinter
hook to collect Tcl modules directory (tcl8
) in addition to Tcl/Tk data directories. (#5175)(GNU/Linux) {PyQt5,PySide2}.QtWebEngineWidgets: fix search for extra NSS libraries to prevent an error on systems where /lib64/nss/*.so comes up empty. (#5149)
(OSX) Avoid collecting data from system Tcl/Tk framework in
tkinter
hook as we do not collect their shared libraries, either. Affects only python versions that still use the system Tcl/Tk 8.5. (#5217)(OSX) Correctly locate the tcl/tk framework bundled with official python.org python builds from v.3.6.5 on. (#5013)
(OSX) Fix the QTWEBENGINEPROCESS_PATH set in PyQt5.QtWebEngineWidgets rthook. (#5183)
(OSX) PySide2.QtWebEngineWidgets: add QtQmlModels to included libraries. (#5150)
(Windows) Remove the obsolete python2.4-era
_handle_broken_tcl_tk
work-around for old virtual environments from thetkinter
hook. (#5222)
Bootloader¶
Fix freeing memory allocted by Python using
free()
instead ofPyMem_RawFree()
. (#4441)(GNU/Linux) Avoid segfault when temp path is missing. (#5255)
(GNU/Linux) Replace a
strncpy()
call inpyi_path_dirname()
withsnprintf()
to ensure that the resulting string is always null-terminated. (#5212)(OSX) Added capability for already-running apps to accept URL & drag’n drop events via Apple Event forwarding (#5276)
(OSX) Bump
MACOSX_DEPLOYMENT_TARGET
from 10.7 to 10.13. (#4627, #4886)(OSX) Fix to reactivate running app on “reopen” (#5295)
(Windows) Use
_wfullpath()
instead of_fullpath()
inpyi_path_fullpath
to allow non-ASCII characters in the path. (#5189)
Documentation¶
Add zlib to build the requirements in the Building the Bootlooder section of the docs. (#5130)
PyInstaller Core¶
Add informative message what do to if RecurrsionError occurs. (#4406, #5156)
Prevent a local directory with clashing name from shadowing a system library. (#5182)
Use module loaders to get module content instea of an quirky way semming from early Python 2.x times. (#5157)
(OSX) Exempt the
Tcl
/Tk
dynamic libraries in the system framework from relative path overwrite. Fix missingTcl
/Tk
dynlib on older python.org builds that still make use of the system framework. (#5172)
Test-suite and Continuous Integration¶
Bootloader build¶
Fix AppImage builds that were broken since PyInstaller 3.6. (#4693)
Update build system to use Python 3.
OSX: Fixed the ineffectiveness of the
--distpath
argument for theBUNDLE
step. (#4892)OSX: Improve codesigning and notarization robustness. (#3550, #5112)
OSX: Use high resolution mode by default for GUI applications. (#4337)
4.0 (2020-08-08)¶
Features¶
Provide setuptools entrypoints to enable other packages to provide PyInstaller hooks specific to that package, along with tests for these hooks.
Maintainers of Python packages requiring hooks are invited to use this new feature and provide up-to-date PyInstaller support along with their package. This is quite easy, see our sample project for more information (#4232, #4301, #4582). Many thanks to Bryan A. Jones for implementing the important parts.
A new package pyinstaller-hooks-contrib provides monthly updated hooks now. This package is installed automatically when installing PyInstaller, but can be updated independently. Many thanks to Legorooj for setting up the new package and moving the hooks there.
Added the
excludes
andincludes
arguments to the hook utility functioncollect_data_files
.Change the hook collection order so that the hook-priority is command line, then entry-point, then PyInstaller builtins. (#4876)
Bugfix¶
(AIX) Include python-malloc labeled libraries in search for libpython. (#4738)
(win32) Fix Security Alerts caused by subtle implementation differences between posix anf windows in
os.path.dirname()
. (#4707)(win32) Fix struct format strings for versioninfo. (#4861)
(Windows) cv2: bundle the opencv_videoio_ffmpeg*.dll, if available. (#4999)
(Windows) GLib: bundle the spawn helper executables for g_spawn* API. (#5000)
(Windows) PySide2.QtNetwork: search for SSL DLLs in PrefixPath in addition to BinariesPath. (#4998)
(Windows) When building with 32-bit python in onefile mode, set the
requestedExecutionLevel
manifest key every time and embed the manifest. (#4992)Allow building on a different drive than the source. (#4820)
Consider Python<version> as possible library binary path. Fixes issue where python is not found if Python3 is installed via brew on OSX (#4895)
Ensure shared dependencies from onefile packages can be opened in the bootloader.
Ensuring repeatable builds of base_library.zip. (#4654)
Fix
FileNotFoundError
showing up inutils/misc.py
which occurs when a namespace was processed as an filename. (#4034)Fix multipackaging. The MERGE class will now have the correct relative paths between shared dependencies which can correctly be opened by the bootloader. (#1527, #4303)
Fix regression when trying to avoid hard-coded paths in .spec files.
Fix SIGTSTP signal handling to allow typing Ctrl-Z from terminal. (#4244)
Update the base library to support encrypting Python bytecode (
--key
option) again. Many thanks to Matteo Bertini for finally fixing this. (#2365, #3093, #3133, #3160, #3198, #3316, #3619, #4241, #4652)When stripping the leading parts of paths in compiled code objects, the longest possible import path will now be stripped. (#4922)
Incompatible Changes¶
Remove support for Python 2.7. The minimum required version is now Python 3.5. The last version supporting Python 2.7 was PyInstaller 3.6. (#4623)
Many hooks are now part of the new pyinstaller-hooks-contrib repository. See below for a detailed list.
Hooks¶
Add hook for
scipy.stats._stats
(needed for scipy since 1.5.0). (#4981)Prevent hook-nltk from adding non-existing directories. (#3900)
Fix
importlib_resources
hook for modern versions (after 1.1.0). (#4889)Fix hidden imports in pkg_resources and packaging (#5044)
Add yet more hidden imports to pkg_resources hook.
Mirror the pkg_resources hook for packaging which may or may not be duplicate of
pkg_resources._vendor.packaging
.
Update pkg_resources hook for setuptools v45.0.0.
Add QtQmlModels to included libraries for QtWebEngine on OS X (#4631).
Fix detecting Qt5 libraries and dependencies from conda-forge builds (#4636).
Add an AssertionError message so that users who get an error due to Hook conflicts can resolve it (#4626).
These hooks have been moved to the new pyinstaller-hooks-contrib repository: BTrees, Crypto, Cryptodome, IPython, OpenGL, OpenGL_accelerate, Xlib, accessible_output2, adios, aliyunsdkcore, amazonproduct, appdirs, appy, astor, astroid, astropy, avro, bacon, boto, boto3, botocore, certifi, clr, countrycode, cryptography, cv2, cx_Oracle, cytoolz, dateparser, dclab, distorm3, dns, docutils, docx, dynaconf, enchant, enzyme, eth_abi, eth_account, eth_hash, eth_keyfile, eth_utils, faker, flex, fmpy, gadfly, gooey, google.*, gst, gtk, h5py, httplib, httplib2, imageio, imageio_ffmpeg, jedi, jinja2, jira, jsonpath_rw_ext, jsonschema, jupyterlab, kinterbasdb, langcodes, lensfunpy, libaudioverse, llvmlite, logilab, lxml, lz4, magic, mako, markdown, migrate, mpl_toolkits, mssql, mysql, nacl, names, nanite, nbconvert, nbdime, nbformat, ncclient, netCDF4, nltk, nnpy, notebook, numba, openpyxl, osgeo, passlib, paste, patsy, pendulum, phonenumbers, pint, pinyin, psychopy, psycopg2, pubsub, pyarrow, pycountry, pycparser, pyexcel, pyexcelerate, pylint, pymssql, pyodbc, pyopencl, pyproj, pysnmp, pytest, pythoncom, pyttsx, pywintypes, pywt, radicale, raven, rawpy, rdflib, redmine, regex, reportlab, reportlab, resampy, selenium, shapely, skimage, sklearn, sound_lib, sounddevice, soundfile, speech_recognition, storm, tables, tcod, tensorflow, tensorflow_corethon, text_unidecode, textdistance, torch, ttkthemes, ttkwidgets, u1db, umap, unidecode, uniseg, usb, uvloop, vtkpython, wavefile, weasyprint, web3, webrtcvad, webview, win32com, wx, xml.dom, xml.sax, xsge_gui, zeep, zmq.
These hooks have been added while now moved to the new pyinstaller-hooks-contrib repository: astor (#4400, #4704), argon2 (#4625) bcrypt. (#4735), (Bluetooth Low Energy platform Agnostic Klient for Python) (#4649) jaraco.text (#4576, #4632), LightGBM. (#4634), xmldiff (#4680), puremagic (identify a file based off it’s magic numbers) (#4709) webassets (#4760), tensorflow_core (to support tensorflow module forwarding logic (#4400, #4704)
These changes have been applied to hooks now moved to the new pyinstaller-hooks-contrib repository
Bootloader¶
Rework bootloader from using strcpy/strncpy with “is this string terminated”-check to use snprintf(); check succes at more places. (This started from fixing GCC warnings for strncpy and strncat.)
Fix: When copying files, too much data was copied in most cases. This corrupted the file and inhibited using shared dependencies. (#4303)
In debug and windowed mode, show the traceback in dialogs to help debug pyiboot01_bootstrap errors. (#4213, #4592)
Started a small test-suite for bootloader basic functions. (#4585)
PyInstaller Core¶
Provide setuptools entrypoints to enable other packages to provide PyInstaller hooks specific to that package, along with tests for these hooks. See https://github.com/pyinstaller/hooksample for more information. (#4232, #4582)
Bootloader build¶
(AIX) The argument -X32 or -X64 is not recognized by the AIX loader - so this code needs to be removed. (#4730, #4731)
(OSX) Allow end users to override MACOSX_DEPLOYMENT_TARGET and mmacosx-version-min via environment variables and set 10.7 as the fallback value for both. (#4677)
Do not print info about
--noconfirm
when option is already being used. (#4727)Update waf to version 2.0.20 (#4839)
Older Versions¶
Changelog for PyInstaller 3.0 – 3.6¶
3.6 (2020-01-09)¶
Important: This is the last release of PyInstaller supporting Python 2.7. Python 2 is end-of-life, many packages are about to drop support for Python 2.7 - or already did it.
[SECURITY] (Win32) Fix CVE-2019-16784: Local Privilege Escalation caused by insecure directory permissions of sys._MEIPATH. This security fix effects all Windows software frozen by PyInstaller in “onefile” mode. While PyInstaller itself was not vulnerable, all Windows software frozen by PyInstaller in “onefile” mode is vulnerable.
If you are using PyInstaller to freeze Windows software using “onefile” mode, you should upgrade PyInstaller and rebuild your software.
(Windows) Allow usage of VSVersionInfo as version argument to EXE again. (#4381, #4539)
(Windows) Fix MSYS2 dll’s are not found by modulegraph. (#4125, #4417)
(Windows) The temporary copy of bootloader used add resources, icons, etc. is not created in –workpath instead of in %TEMP%. This fixes issues on systems where the anti-virus cleans %TEMP% immediately. (#3869)
Do not fail the build when
ldconfig
is missing/inoperable. (#4261)Fixed loading of IPython extensions. (#4271)
Fixed pre-find-module-path hook for distutils to be compatible with virtualenv >= 16.3. (#4064, #4372)
Improve error reporting when the Python library can’t be found. (#4162)
Add hook for avro (serialization and RPC framework) (#4388), django-babel (#4516), enzyme (#4338), google.api (resp. google.api.core) (#3251), google.cloud.bigquery (#4083, #4084), google.cloud.pubsub (#4446), google.cloud.speech (#3888), nnpy (#4483), passlib (#4520), pyarrow (#3720, #4517), pyexcel and its plugins io, ods, ods3, odsr, xls, xlsx, xlsxw (#4305), pysnmp (#4287), scrapy (#4514), skimage.io (#3934), sklearn.mixture (#4612), sounddevice on macOS and Windows (#4498), text-unidecode (#4327, #4530), the google-cloud-kms client library (#4408), ttkwidgets (#4484), and webrtcvad (#4490).
Correct the location of Qt translation files. (#4429)
Exclude imports for pkg_resources to fix bundling issue. (#4263, #4360)
Fix hook for pywebview to collect all required libraries and data-files. (#4312)
Fix hook numpy and hook scipy to account for differences in location of extra dlls on Windows. (#4593)
Fix pysoundfile hook to bundle files correctly on both OSX and Windows. (#4325)
Fixed hook for pint to also copy metadata as required to retrieve the version at runtime. (#4280)
Fixed PySide2.QtNetwork hook by mirroring PyQt5 approach. (#4467, #4468)
Hook for pywebview now collects data files and dynamic libraries only for the correct OS (Windows). Hook for pywebview now bundles only the required ‘lib’ subdirectory. (#4375)
Update hooks related to PySide2.QtWebEngineWidgets, ensure the relevant supporting files required for a QtWebEngineView are copied into the distribution. (#4377)
Update PyQt5 loader to support PyQt >=5.12.3. (#4293, #4332)
Update PyQt5 to package 64-bit SSL support DLLs. (#4321)
Update PyQt5 to place OpenGL DLLs correctly for PyQt >= 5.12.3. (#4322)
(GNU/Linux) Make hook for GdkPixbuf compatible with Ubuntu and Debian (#4486).
(OSX): Added support for appending URL to program arguments when applications is launched from custom protocol handler. (#4397, #4399)
(POSIX) For one-file binaries, if the program is started via a symlink, the second process now keeps the basename of the symlink. (#3823, #3829)
(Windows) If bundled with the application, proactivley load
ucrtbase.dll
before loading the Python library. This works around unresolved symbol errors when loadingpython35.dll
(or later) on legacy Windows (7, 8, 8.1) systems with Universal CRT update is not installed. (#1566, #2170, #4230)Add our own implementation for
strndup
andstrnlen
to be used on platforms one of these is missing.
Add a check whether
strndup
andstrnlen
are available.Added OpenBSD support. (#4545)
Fix build on Solaris 10.
Fix checking for compiler flags in configure phase. The check for compiler flags actually did never work. (#4278)
Update url for public key in update-waf script. (#4584)
Update waf to version 2.0.19.
3.5 (2019-07-09)¶
(Windows) Force
--windowed
option if first script is a.pyw
file. This might still be overwritten in the spec-file. (#4001)Add support for relative paths for icon-files, resource-files and version-resource-files. (#3333, #3444)
Add support for the RedHat Software Collections (SCL) Python 3.x. (#3536, #3881)
Install platform-specific dependencies only on that platform. (#4166, #4173)
New command-line option
--upx-exclude
, which allows the user to prevent binaries from being compressed with UPX. (#3821)
(conda) Fix detection of conda/anaconda platform.
(GNU/Linux) Fix Anaconda Python library search. (#3885, #4015)
(Windows) Fix UAC in one-file mode by embedding the manifest. (#1729, #3746)
(Windows\Py3.7) Now able to locate pylib when VERSION.dll is listed in python.exe PE Header rather than pythonXY.dll (#3942, #3956)
Avoid errors if PyQt5 or PySide2 is referenced by the modulegraph but isn’t importable. (#3997)
Correctly parse the
--debug=import
,--debug=bootloader
, and--debug=noarchive
command-line options. (#3808)Don’t treat PyQt5 and PySide2 files as resources in an OS X windowed build. Doing so causes the resulting frozen app to fail under Qt 5.12. (#4237)
Explicitly specify an encoding of UTF-8 when opening all text files. (#3605)
Fix appending the content of
datas
in a spec files tobinaries
instead of the internaldatas
. (#2326, #3694)Fix crash when changing from
--onefile
to--onedir
on consecutive runs. (#3662)Fix discovery of Qt paths on Anaconda. (#3740)
Fix encoding error raised when reading a XML manifest file which includes non-ASCII characters. This error inhibited building an executable which has non-ASCII characters in the filename. (#3478)
Fix inputs to
QCoreApplication
constructor inQt5LibraryInfo
. Now the core application’s initialization and finalization in addition to system-wide and application-wide settings is safer. (#4121)Fix installation with pip 19.0. (#4003)
Fixes PE-file corruption during version update. (#3142, #3572)
In the fake ´site` module set USER_BASE to empty string instead of None as Jupyter Notebook requires it to be a ‘str’. (#3945)
Query PyQt5 to determine if SSL is supported, only adding SSL DLLs if so. In addition, search the path for SSL DLLs, instead of looking in Qt’s
BinariesPath
. (#4048)Require
pywin32-ctypes
version 0.2.0, the minimum version which supports Python 3.7. (#3763)Use pkgutil instead of filesystem operations for interacting with the modules. (#4181)
PyInstaller is no longer tested against Python 3.4, which is end-of-live.
Functions
compat.architecture()
,compat.system()
andcompat.machine()
have been replace by variables of the same name. This avoids evaluating the save several times.Require an option for the
--debug
argument, rather than assuming a default ofall
. (#3737)
Added hooks for aliyunsdkcore (#4228), astropy (#4274), BTrees (#4239), dateparser.utils.strptime (#3790), faker (#3989, #4133), gooey (#3773), GtkSourceView (#3893), imageio_ffmpeg (#4051), importlib_metadata and importlib_resources (#4095), jsonpath_rw_ext (#3841), jupyterlab (#3951), lz4 (#3710), magic (#4267), nanite (#3860), nbconvert (#3947), nbdime (#3949), nbformat (#3946), notebook (#3950), pendulum (#3906), pysoundfile (#3844), python-docx (#2574, #3848), python-wavefile (#3785), pytzdata (#3906), PyWavelets pywt (#4120), pywebview (#3771), radicale (#4109), rdflib (#3708), resampy (#3702), sqlalchemy-migrate (#4250), textdistance (#4239), tcod (#3622), ttkthemes (#4105), and umap-learn (#4165).
Add runtime hook for certifi. (#3952)
Updated hook for ‘notebook’ to look in all Jupyter paths reported by jupyter_core. (#4270)
Fixed hook for ‘notebook’ to only include directories that actually exist. (#4270)
Fixed pre-safe-import-module hook for setuptools.extern.six. (#3806)
Fixed QtWebEngine hook on OS X. (#3661)
Fixed the QtWebEngine hook on distributions which don’t have a NSS subdir (such as Archlinux) (#3758)
Include dynamically-imported backends in the
eth_hash
package. (#3681)Install platform-specific dependencies only on that platform. (#4168)
Skip packaging PyQt5 QML files if the QML directory doesn’t exist. (#3864)
Updated PySide2 hooks to follow PyQt5 approach. (#3655, #3689, #3724, #4040, #4103, #4136, #4175, #4177, #4198, #4206)
Updated the jsonschema hook for v3.0+. (#4100)
Updated the Sphinx hook to correctly package Sphinx 1.8.
Update the text produced by
--help
to state that the--debug
argument requires an option. Correctly format this argument in the Sphinx build process. (#3737)
Remove the PEP-518 “build-system” table from
pyproject.toml
to fix installation with pip 19.0.
Add support for folders in COLLECT and BUNDLE. (#3653)
Completely remove pywin32 dependency, which has erratic releases and the version on pypi may no longer have future releases. Require pywin32-ctypes instead which is pure python. (#3728, #3729)
modulegraph: Align with upstream version 0.17.
Now prints a more descriptive error when running a tool fails (instead of dumping a trace-back). (#3772)
Suppress warnings about missing UCRT dependencies on Win 10. (#1566, #3736)
Fix Appveyor failures of
test_stderr_encoding()
andtest_stdout_encoding()
on Windows Python 3.7 x64. (#4144)November update of packages used in testing. Prevent pyup from touching
test/requirements-tools.txt
. (#3845)Rewrite code to avoid a
RemovedInPytest4Warning: Applying marks directly to parameters is deprecated, please use pytest.param(..., marks=...) instead.
Run Travis tests under Xenial; remove the deprecated
sudo: false
tag. (#4140)Update the Markdown test to comply with Markdown 3.0 changes by using correct syntax for extensions.
3.4 (2018-09-09)¶
Add support for Python 3.7 (#2760, #3007, #3076, #3399, #3656), implemented by Hartmut Goebel.
Improved support for Qt5-based applications (#3439). By emulating much of the Qt deployment tools’ behavior most PyQt5 variants are supported. However, Anaconda’s PyQt5 packages are not supported because its
QlibraryInfo
implementation reports incorrect values. CI tests currently run on PyQt5 5.11.2. Many thanks to Bryan A. Jones for taking this struggle.--debug
now allows more debugging to be activated more easily. This includes bootloader messages, Python’s “verbose imports” and store collected Python files in the output directory instead of freezing. Seepyinstaller –-help
for details. (#3546, #3585, #3587)Hint users to install development package for missing pyconfig.h. (#3348)
In
setup.py
specify Python versions this distribution is compatible with.Make
base_library.zip
reproducible: Set time-stamp of files. (#2952, #2990)New command-line option
--bootloader-ignore-signals
to make the bootloader forward all signals to the bundle application. (#208, #3515)(OS X) Python standard library module
plistlib
is now used for generating theInfo.plist
file. This allows passing complex and nested data ininfo_plist
. (#3532, #3541)
Add missing
warnings
module tobase_library.zip
. (#3397, #3400)Fix and simplify search for libpython on Windows, msys2, cygwin. (#3167, #3168)
Fix incompatibility with pycryptodome (a replacement for the apparently abandoned pycrypto library) when using encrypted PYZ-archives. (#3537)
Fix race condition caused by the bootloader parent process terminating before the child is finished. This might happen e.g. when the child process itself plays with
switch_root
. (#2966)Fix wrong security alert if a filename contains
..
. (#2641, #3491)Only update resources of cached files when necessary to keep signature valid. (#2526)
(OS X) Fix: App icon appears in the dock, even if
LSUIElement=True
. (#1917, #2075, #3566)(Windows) Fix crash when trying to add resources to Windows executable using the
--resource
option. (#2675, #3423)(Windows) Only update resources when necessary to keep signature valid (#3323)
(Windows) Use UTF-8 when reading XML manifest file. (#3476)
(Windows) utils/win32: trap invalid
--icon
arguments and terminate with a message. (#3126)
Drop support for Python 3.3 (#3288), Thanks to Hugo and xoviat.
--debug
now expects an (optional) argument. Thus using… --debug script.py
will break. Use… script.py --debug
or… --debug=all script.py
instead. Also--debug=all
(which is the default if no argument is given) includesnoarchive
, which will store all collected Python files in the output directory instead of freezing them. Use--debug=bootloader
to get the former behavior. (#3546, #3585, #3587)(minor) Change naming of intermediate build files and the warn file. This only effects 3rd-party tools (if any exists) relying on the names of these files.
(minor) The destination path for
--add-data
and--add-binary
must no longer be empty, use.
instead. (#3066)(minor) Use standard path, not dotted path, for C extensions (Python 3 only).
New hooks for bokeh visualization library (#3607), Champlain, Clutter (#3443) dynaconf (#3641), flex (#3401), FMPy (#3589), gi.repository.xlib (#2634, #3396) google-cloud-translate, google-api-core (#3658), jedi (#3535, #3612), nltk (#3705), pandas (#2978, #2998, #2999, #3015, #3063, #3079), phonenumbers (#3381, #3558), pinyin (#2822), PySide.phonon, PySide.QtSql (#2859), pytorch (#3657), scipy (#2987, #3048), uvloop (#2898), web3, eth_account, eth_keyfile (#3365, #3373).
Updated hooks for Cryptodome 3.4.8, Django 2.1, gevent 1.3. Crypto (support for PyCryptodome) (#3424), Gst and GdkPixbuf (to work on msys2, #3257, #3387), sphinx 1.7.1, setuptools 39.0.
Updated hooks for PyQt5 (#1930, #1988, #2141, #2156, #2220, #2518, #2566, #2573, #2577, #2857, #2924, #2976, #3175, #3211, #3233, #3308, #3338, #3417, #3439, #3458, #3505), among others:
Fix hooks for cryptodome (#3405), PySide2 (style mismatch) (#3374, #3578)
Fix missing SSL libraries on Windows with
PyQt5.QtNetwork
. (#3511, #3520)Fix zmq on Windows Python 2.7. (#2147)
(GNU/Linux) Fix hook usb: Resolve library name reported by usb.backend. (#2633, #2831, #3269)
Clean up the USB hook logic.
Forward all signals to the child process if option
pyi-bootloader-ignore-signals
to be set in the archive. (#208, #3515)Use
waitpid
instead ofwait
to avoid the bootloder parent process gets signaled. (#2966)(OS X) Don’t make the application a GUI app by default, even in
--windowed
mode. Not enforcing this programmatically in the bootloader allows to control behavior usingInfo.plist
options - which can by set in PyInstaller itself or in the .spec-file. (#1917, #2075, #3566)(Windows) Show respectivly print utf-8 debug messages ungarbled. (#3477)
Fix
setenv()
call whenHAVE_UNSETENV
is not defined. (#3722, #3723)
Fix typos, smaller errors and formatting errors in documentation. (#3442, #3521, #3561, #3638)
Make clear that
--windowed
is independent of--onedir
. (#3383)Mention imports using imports
imp.find_module()
are not detected.Reflect actual behavior regarding
LD_LIBRARY_PATH
. (#3236)(OS X) Revise section on
info_plist
forplistlib
functionality and use an example more aligned with real world usage. (#3532, #3540, #3541)(developers) Overhaul guidelines for commit and commit-messages. (#3466)
(developers) Rework developer’s quick-start guide.
Add
requirements_for_package()
andcollect_all()
helper functions for hooks.Add a explanatory header to the warn-file, hopefully reducing the number of those posting the file to the issue tracker.
Add module
enum
to base_library.zip, required for modulere
in Python 3.6 (andre
is required bywarnings
).Always write the warn file.
Apply
format_binaries_and_datas()
(which converts hook-style tuples intoTOC
-style tuples) to binaries and datas added through the hook api.Avoid printing a useless exceptions in the
get_module_file_attribute()
helper function..Don’t gather Python extensions in
collect_dynamic_libc()
.Fix several ResourceWarnings and DeprecationWarnings (#3677)
Hint users to install necessary development packages if, in
format_binaries_and_datas()
, the file not found ispyconfig.h
. (#1539, #3348)Hook helper function
is_module_satisfies()
returnsFalse
for packages not found. (#3428, #3481)Read data for cache digest in chunks. (#3281)
Select correct file extension for C-extension file-names like
libzmq.cp36-win_amd64.pyd
.State type of import (conditional, delayed, etc.) in the warn file again.
(modulegraph) Unbundle altgraph library, use from upstream. (#3058)
(OS X) In
--console
mode setLSBackgroundOnly=True
in``Info.plist`` to hide the app-icon in the dock. This can still be overruled by passinginfo_plist
in the .spec-file. (#1917, #3566)(OS X) Use the python standard library
plistlib
for generating theInfo.plist
file. (#3532, #3541)(Windows) Completely remove pywin32 dependency, which has erratic releases and the version on pypi may no longer have future releases. Require pywin32-ctypes instead, which is pure python. (#3141)
(Windows) Encode manifest before updating resource. (#3423)
(Windows) Make import compatible with python.net, which uses an incompatible signature for
__import__
. (#3574)
Add script and dockerfile for running tests in docker. (Contributed, not maintained) (#3519)
Avoid log messages to be written (and captured) twice.
Fix decorator
skipif_no_compiler
.Fix the test for the “W” run-time Python option to verify module warnings can actually be imported. (#3402, #3406)
Fix unicode errors when not capturing output by pytest.
Run
pyinstaller -h
to verify it works.test_setuptools_nspkg
no longer modifies source files.Appveyor:
Add documentation for Appveyor variables used to
appveyor.yml
.Significantly clean-up appveyor.yml (#3107)
Additional tests produce > 1 hour runs. Split each job into two jobs.
Appveyor tests run on 2 cores; therefore, run 2 jobs in parallel.
Reduce disk usage.
Split Python 2.7 tests into two jobs to avoid the 1 hour limit.
Update to use Windows Server 2016. (#3563)
Travis
Print invoking python version when compiling.
Update waf build-tool to 2.0.9 and fix our
wscript
for waf 2.0.(GNU/Linux) When building with
--debug
turn of FORTIFY_SOURCE to ease debugging.
Anaconda’s PyQt5 packages are not supported because its
QlibraryInfo
implementation reports incorrect values.All scripts frozen into the package, as well as all run-time hooks, share the same global variables. This issue exists since v3.2 but was discovered only lately, see #3037. This may lead to leaking global variables from run-time hooks into the script and from one script to subsequent ones. It should have effects in rare cases only, though.
Data-files from wheels, unzipped eggs or not ad egg at all are not included automatically. This can be worked around using a hook-file, but may not suffice when using
--onefile
and something like python-daemon.The multipackage (MERGE) feature (#1527) is currently broken.
(OSX) Support for OpenDocument events (#1309) is broken.
(Windows) With Python 2.7 the frozen application may not run if the user-name (more specifically
%TEMPDIR%
) includes some Unicode characters. This does not happen with all Unicode characters, but only some and seems to be a windows bug. As a work-around please upgrade to Python 3 (#2754, #2767).(Windows) For Python >= 3.5 targeting Windows < 10, the developer needs to take special care to include the Visual C++ run-time .dlls. Please see the section Platform-specific Notes in the manual. (#1566)
3.3.1 (2017-12-13)¶
Fix imports in hooks accessible_output and sound_lib (#2860).
Fix ImportError for sysconfig for 3.5.4 Conda (#3105, #3106).
Fix shapely hook for conda environments on Windows (#2838).
Add hook for unidecode.
(Windows) Pre-build bootloaders (and custom-build ones using MSVC) can be used on Windows XP again. Set minimum target OS to XP (#2974).
Fix build for FreeBSD (#2861, #2862).
Usage: Add help-message clarifying use of options when a spec-file is provided (#3039).
Add printing infos on UnicodeDecodeError in exec_command(_all).
(win32) Issue an error message on errors loading the icon file (#2039).
(aarch64) Use correct bootloader for 64-bit ARM (#2873).
(OS X) Fix replacement of run-time search path keywords (
@…
) (#3100).Modulegraph
Fix recursion too deep errors cause by reimporting SWIG-like modules (#2911, #3040, #3061).
Keep order of imported identifiers.
In Continuous Integration tests: Enable flake8-diff linting. This will refuse all changed lines not following PEP 8.
Enable parallel testing on Windows,
Update requirements.
Add more test cases for modulegraph.
Fix a test-case for order of module import.
Add test-cases to check scripts do not share the same global vars (see Known Issues).
Add clarification about treatment of options when a spec-file is provided (#3039).
Add docs for running PyInstaller with Python optimizations (#2905).
Add notes about limitations of Cython support.
Add information how to handle undetected ctypes libraries.
Add notes about requirements and restrictions of SWIG support.
Add note to clarify what binary files are.
Add a Development Guide.
Extend “How to Contribute”.
Add “Running the Test Suite”.
Remove badges from the Readme (#2853).
Update outdated sections in man-pages and otehr enhancements to the man-page.
All scripts frozen into the package, as well as all run-time hooks, share the same global variables. This issue exists since v3.2 but was discovered only lately, see #3037. This may lead to leaking global variables from run-time hooks into the script and from one script to subsequent ones. It should have effects in rare cases only, though.
Further see the Known Issues for release 3.3.
3.3 (2017-09-21)¶
Add Support for Python 3.6! Many thanks to xiovat! (#2331, #2341)
New command line options for adding data files (
--datas
, #1990) and binaries (--binaries
, #703)Add command line option ‘–runtime-tmpdir’.
Bootloaders for Windows are now build using MSVC and statically linked with the run-time-library (CRT). This solved a lot of issues related to .dlls being incompatible with the ones required by
python.dll
.Bootloaders for GNU/Linux are now officially no LSB binaries. This was already the case since release 3.1, but documented the other way round. Also the build defaults to non-LSB binaries now. (#2369)
We improved and stabilized both building the bootloaders and the continuous integration tests. See below for details. Many thanks to all who worked on this.
To ease solving issues with packages included wrongly, the html-file with a cross-reference is now always generated. It’s visual appearance has been modernized (#2765).
Command-line option obsoleted several version ago are not longer handled gracefully but raise an error (#2413)
Installation: PyInstaller removed some internal copies of 3rd-party packages. These are now taken from their official releases at PyPI (#2589). This results in PyInstaller to no longer can be used from just an unpacked archive, but needs to be installed like any Python package. This should effect only a few people, e.g. the developers.
Following PEP 527, we only release one source archive now and decided to use .tar.gz (#2754).
New and Updated hooks: accessible_output2 (#2266), ADIOS (#2096), CherryPy (#2112), PySide2 (#2471, #2744) (#2472), Sphinx (#2612, 2708) (#2708), appdir (#2478), clr (#2048), cryptodome (#2125), cryptography (#2013), dclab (#2657), django (#2037), django migrations (#1795), django.contrib (#2336), google.cloud, google.cloud.storage, gstreamer (#2603), imageio (#2696), langcodes (#2682), libaudioverse (#2709), mpl_toolkits (#2400), numba, llvmlite (#2113), openpyxl (#2066), pylint, pymssql, pyopencl, pyproj (#2677), pytest (#2119), qtawesome (#2617), redmine, requests (#2334), setuptools, setuptools (#2565), shapely (#2569), sound_lib (#2267), sysconfig, uniseg (#2683), urllib3, wx.rc (#2295),
numpy: Look for .dylib libraries, too ( (#2544), support numpy MKL builds (#1881, #2111)
osgeo: Add conda specific places to check for auxiliary data (#2401)
QT and related
Add hooks for PySide2
Eliminate run-time hook by placing files in the correct directory
Fix path in homebrew for searching for qmake (#2354)
Repair Qt dll location (#2403)
Bundle PyQT 5.7 DLLs (#2152)
PyQt5: Return qml plugin path including subdirectory (#2694)
Fix hooks for PyQt5.QtQuick (#2743)
PyQt5.QtWebEngineWidgets: Include files needed by QWebEngine
GKT+ and related
Fix Gir file path on windows.
Fix unnecessary file search & generation when GI’s typelib is exists
gi: change gir search path when running from a virtualenv
gi: package gdk-pixbuf in osx codesign agnostic dir
gi: rewrite the GdkPixbuf loader cache at runtime on Linux
gi: support onefile mode for GdkPixbuf
gi: support using gdk-pixbuf-query-loaders-64 when present
gi: GIR files are only required on OSX
gio: copy the mime.cache also
Fix hooks for PyGObject on windows platform (#2306)
Fixed hooks: botocore (#2384), clr (#1801), gstreamer (#2417), h5py (#2686), pylint, Tix data files (#1660), usb.core (#2088), win32com on non-windows-systems (#2479)
Fix
multiprocess
spawn mode on POSIX OSs (#2322, #2505, #2759, #2795).
Add tempdir option to control where bootloader will extract files (#2221)
(Windows) in releases posted on PyPI requires msvcr*.dll (#2343)
Fix unsafe string manipulation, resource and memory leaks. Thanks to Vito Kortbeek (#2489, #2502, #2503)
Remove a left-over use of
getenv()
Set proper LISTEN_PID (set by systemd) in child process (#2345)
Adds PID to bootloader log messages (#2466, #2480)
(Windows) Use _wputenv_s() instead of
SetEnvironmentVariableW()
(Windows) Enhance error messages (#1431)
(Windows) Add workaround for a Python 3 issue http://bugs.python.org/issue29778 (#2496, #2844)
(OS X): Use single process for –onedir mode (#2616, #2618)
(GNU/Linux) Compile bootloaders with –no-lsb by default (#2369)
(GNU/Linux) Fix: linux64 bootloader requires glibc 2.14 (#2160)
(GNU/Linux) set_dynamic_library_path change breaks plugin library use (#625)
The bootloader build was largely overhauled. In the wscript, the build no longer depends on the Python interpreter’s bit-size, but on the compiler. We have a machine for building bootloaders for Windows and cross-building for OS X. Thus all mainteriner are now able to build the bootloaders for all supported platforms.
Add “official” build-script.
(GNU/Linux) Make –no-lsb the default, add option –lsb.
Largely overhauled Vagrantfile:
Make Darwin bootloaders build in OS X box (unused)
Make Windows bootloaders build using MSVC
Allow specifying cross-target on linux64.
Enable cross-building for OS X.
Enable cross-building for Windows (unused)
Add box for building osxcross.
Largely overhauled wscript:
Remove options –target-cpu.
Use compiler’s target arch, not Python’s.
Major overhaul of the script
Build zlib if required, not if “on windows”.
Remove obsolete warnings.
Update Solaris, AIX and HPUX support.
Add flags for ‘strip’ tool in AIX platform.
Don’t set POSIX / SUS version defines.
(GNU/Linux) for 64-bit arm/aarch ignore the gcc flag
-m64
(#2801).
Implement PEP-451 ModuleSpec type import system (#2377)
Fix: Import not thread-save? (#2010, #2371)
Analyze: Check Python version when testing whether to rebuild.
Analyze: Don’t fail on syntax error in modules, simply ignore them.
Better error message when datas are not found. (#2308)
Building: OSX: Use unicode literals when creating Info.plist XML
Building: Don’t fail if “datas” filename contain glob special characters. (#2314)
Building: Read runtime-tmpdir from .spec-file.
Building: Update a comment.
building: warn users if bincache gets corrupted. (#2614)
Cli-utils: Remove graceful handling of obsolete command line options.
Configure: Create new parent-dir when moving old cache-dir. (#2679)
Depend: Include vcruntime140.dll on Windows. (#2487)
Depend: print nice error message if analyzed script has syntax error.
Depend: When scanning for ctypes libs remove non-basename binaries.
Enhance run-time error message on ctypes import error.
Fix #2585: py2 non-unicode sys.path been tempted by os.path.abspath(). (#2585)
Fix crash if extension module has hidden import to ctypes. (#2492)
Fix handling of obsolete command line options. (#2411)
Fix versioninfo.py breakage on Python 3.x (#2623)
Fix: “Unicode-objects must be encoded before hashing” (#2124)
Fix: UnicodeDecodeError - collect_data_files does not return filenames as unicode (#1604)
Remove graceful handling of obsolete command line options. (#2413)
Make grab version more polite on non-windows (#2054)
Make utils/win32/versioninfo.py round trip the version info correctly.
Makespec: Fix version number processing for PyCrypto. (#2476)
Optimizations and refactoring to modulegraph and scanning for ctypes dependencies.
pyinstaller should not crash when hitting an encoding error in source code (#2212)
Remove destination for COLLECT and EXE prior to copying it (#2701)
Remove uninformative traceback when adding not found data files (#2346)
threading bug while processing imports (#2010)
utils/hooks: Add logging to collect_data_files.
(win32) Support using pypiwin32 or pywin32-ctypes (#2602)
(win32) Use os.path.normpath to ensure that system libs are excluded.
(win32) Look for libpython%.%.dll in Windows MSYS2 (#2571)
(win32) Make versioninfo.py round trip the version info correctly (#2599)
(win32) Ensure that pywin32 isn’t imported before check_requirements is called
(win32) pyi-grab_version and –version-file not working? (#1347)
(win32) Close PE() object to avoid mmap memory leak (#2026)
(win32) Fix: ProductVersion in windows version info doesn’t show in some cases (#846)
(win32) Fix multi-byte path bootloader import issue with python2 (#2585)
(win32) Forward DYLD_LIBRARY_PATH through arch command. (#2035)
(win32) Add
vcruntime140.dll
to_win_includes for Python 3.5 an 3.6 (#2487)(OS X) Add libpython%d.%dm.dylib to Darwin (is_darwin) PYDYLIB_NAMES. (#1971)
(OS X) macOS bundle Info.plist should be in UTF-8 (#2615)
(OS X) multiprocessing spawn in python 3 does not work on macOS (#2322)
(OS X) Pyinstaller not able to find path (@rpath) of dynamic library (#1514)
Modulegraph
Align with upstream version 0.13.
Add the upstream test-suite
Warn on syntax error and unicode error. (#2430)
Implement
enumerate_instructions()
(#2720)Switch byte-code analysis to use Instruction (like dis3 does) (#2423)
Log warning on unicode error instead of only a debug message (#2418)
Use standard logging for messages. (#2433)
Fix to reimport failed SWIG C modules (1522, #2578).
Included 3rd-party libraries
Remove bundled
pefile
andmacholib
, use the releases from PyPI. (#1920, #2689)altgraph: Update to altgraph 0.13, add upstream test-suite.
grab_version.py: Display a friendly error message when utility fails (#859, #2792).
Rearrange requirements files.
Pin required versions – now updated using pyup (#2745)
Hide useless trace-backs of helper-functions.
Add a test for PyQt5.QtQuick.
Add functional tests for PySide2
Add test for new feature –runtime-tmpdir.
Fix regression-test for #2492.
unit: Add test-cases for PyiModuleGraph.
unit/altgraph: Bringing in upstream altgraph test-suite.
unit/modulegraph: Bringing in the modulegraph test-suite.
Continuous Integration
Lots of enhancements to the CI tests to make them more stabile and reliable.
Pin required versions – now updated using pyup (#2745)
OS X is now tested along with GNU/Linux at Travis CI (#2508)
Travis: Use stages (#2753)
appveyor: Save cache on failure (#2690)
appveyor: Verify built bootloaders have the expected arch.
Add information how to donate (#2755, #2772).
Add how to install the development version using pip.
Fix installation instructions for development version. (#2761)
Better examples for hidden imports.
Clarify and fix “Adding Data Files” and “Adding Binary Files”. (#2482)
Document new command line option ‘–runtime-tmpdir’.
pyinstaller works on powerpc linux, big endian arch (#2000)
Largely rewrite section “Building the Bootloader”, update from the wiki page.
Describe building LSB-compliant bootloader as (now) special case.
help2rst: Add cross-reference labels for option-headers.
Enable sphinx.ext.intersphinx and links to our website.
Sphinx should not “adjust” display of command line documentation (#2217)
Data-files from wheels, unzipped eggs or not ad egg at all are not included automatically. This can be worked around using a hook-file, but may not suffice when using
--onefile
and something like python-daemon.The multipackage (MERGE) feature (#1527) is currently broken.
(OSX) Support for OpenDocument events (#1309) is broken.
(Windows) With Python 2.7 the frozen application may not run if the user-name (more specifically
%TEMPDIR%
) includes some Unicode characters. This does not happen with all Unicode characters, but only some and seems to be a windows bug. As a work-around please upgrade to Python 3 (#2754, #2767).(Windows) For Python >= 3.5 targeting Windows < 10, the developer needs to take special care to include the Visual C++ run-time .dlls. Please see the section Platform-specific Notes in the manual. (#1566)
For Python 3.3, imports are not thread-safe (#2371#). Since Python 3.3 is end of live at 2017-09-29, we are not going to fix this.
3.2.1 (2017-01-15)¶
New, updated and fixed hooks: botocore (#2094), gi (#2347), jira (#2222), PyQt5.QtWebEngineWidgets (#2269), skimage (#2195, 2225), sphinx (#2323,) xsge_gui (#2251).
Fixed the following issues:
Don’t fail if working directory already exists (#1994)
Avoid encoding errors in main script (#1976)
Fix hasher digest bytes not str (#2229, #2230)
(Windows) Fix additional dependency on the msvcrt10.dll (#1974)
(Windows) Correctly decode a bytes object produced by pefile (#1981)
(Windows) Package
pefile
with pyinstaller. This partially undoes some changes in 3.2 in which the packaged pefiles were removed to use the pypi version instead. The pypi version was considerably slower in some applications, and still has a couple of small issues on PY3. (#1920)(OS X) PyQt5 packaging issues on MacOS (#1874)
(OS X) Replace run-time search path keyword (#1965)
(OS X) (Re-) add argv emulation for OSX, 64-bit (#2219)
(OS X) use decode(“utf-8”) to convert bytes in getImports_macholib() (#1973)
(Bootloader) fix segfaults (#2176)
(setup.py) pass option –no-lsb on GNU/Linux only (#1975)
Updates and fixes in documentation, manuals, et al. (#1986, 2002, #2153, #2227, #2231)
3.2 (2016-05-03)¶
Even the “main” script is now byte-compiled (#1847, #1856)
The manual is on readthedocs.io now (#1578)
On installation try to compile the bootloader if there is none for the current plattform (#1377)
(Unix) Use
objcopy
to create a valid ELF file (#1812, #1831)(Linux): Compile with
_FORTIFY_SOURCE
(#1820)New, updated and fixed hooks: CherryPy (#1860), Cryptography (#1425, #1861), enchant (1562), gi.repository.GdkPixbuf (#1843), gst (#1963), Lib2to3 (#1768), PyQt4, PyQt5, PySide (#1783, #1897, #1887), SciPy (#1908, #1909), sphinx (#1911, #1912), sqlalchemy (#1951), traitlets wx.lib.pubsub (#1837, #1838),
For windowed mode add
isatty()
for our dummy NullWriter (#1883)Suppress “Failed to execute script” in case of SystemExit (#1869)
Do not apply Upx compressor for bootloader files (#1863)
Fix absolute path for lib used via ctypes (#1934)
(OSX) Fix binary cache on NFS (#1573, #1849)
(Windows) Fix message in grab_version (#1923)
(Windows) Fix wrong icon paramter in Windows example (#1764)
(Windows) Fix win32 unicode handling (#1878)
(Windows) Fix unnecessary rebuilds caused by rebuilding winmanifest (#1933)
(Cygwin) Fix finding the Python library for Cygwin 64-bit (#1307, #1810, #1811)
(OSX) Fix compilation issue (#1882)
(Windows) No longer bundle
pefile
, use package from pypi for windows (#1357)(Windows) Provide a more robust means of executing a Python script
AIX fixes.
Update waf to version 1.8.20 (#1868)
Fix excludedimports, more predictable order how hooks are applied #1651
Internal impovements and code clean-up (#1754, #1760, #1794, #1858, #1862, #1887, #1907, #1913)
Clean-ups fixes and improvements for the test suite
Known Issues
Apps built with Windows 10 and Python 3.5 may not run on Windows versions earlier than 10 (#1566).
The multipackage (MERGE) feature (#1527) is currently broken.
(OSX) Support for OpenDocument events (#1309) is broken.
3.1.1 (2016-01-31)¶
Fixed the following issues:
Fix problems with setuptools 19.4 (#1772, #1773, #1790, #1791)
3.1 does not collect certain direct imports (#1780)
Git reports wrong version even if on unchanged release (#1778)
Don’t resolve symlinks in modulegraph.py (#1750, #1755)
ShortFileName not returned in win32 util (#1799)
3.1 (2016-01-09)¶
Support reproducible builds (#490, #1434, #1582, #1590).
Strip leading parts of paths in compiled code objects (#1059, #1302, #1724).
With
--log-level=DEBUG
, a dependency graph-file is emitted in the build-directory.Allow running pyinstaller as user root. By popular demand, see e.g. #1564, #1459, #1081.
New Hooks: botocore, boto3, distorm3, GObject, GI (G Introspection), GStreamer, GEvent, kivy, lxml.isoschematron, pubsub.core, PyQt5.QtMultimedia, scipy.linalg, shelve.
Fixed or Updated Hooks: astroid, django, jsonschema logilab, PyQt4, PyQt5, skimage, sklearn.
Add option
--hiddenimport
as an alias for--hidden-import
.(OSX): Fix issues with
st_flags
(#1650).(OSX) Remove warning message about 32bit compatibility (#1586).
(Linux) The cache is now stored in
$XDG_CACHE_HOME/pyinstaller
instead of$XDG_DATA_HOME
- the cache is moved automatically (#1118).Documentation updates, e.g. about reproducible builds
Put back full text of GPL license into COPYING.txt.
Fix crashes when looking for ctypes DLLs (#1608, #1609, #1620).
Fix: Imports in byte-code not found if code contains a function (#1581).
Fix recursion into bytes-code when scanning for ctypes (#1620).
Fix PyCrypto modules to work with crypto feature (
--key
option) (#1663).Fix problems with
excludedimports
in some hook excluding the named modules even if used elswhere (#1584, #1600).Fix freezing of pip 7.1.2 (#1699).
FreeBSD and Solaris fixes.
Search for
ldconfig
in $PATH first (#1659)Deny processing outdated package
_xmlplus
.Improvements to the test-suite, testing infrastructure and continuous integration.
For non-release builds, the exact git revision is not used.
Internal code refactoring.
Enhancements and clean-ups to the hooks API - only relevant for hook authors. See the manual for details. E.g:
Removed
attrs
in hooks - they were not used anymore anyway.Change
add/del_import()
to accept arbitrary number of module names.New hook utility function
copy_metadata()
.
Known Issues
Apps built with Windows 10 and Python 3.5 may not run on Windows versions earlier than 10 (#1566).
The multipackage (MERGE) feature (#1527) is currently broken.
(OSX) Support for OpenDocument events (#1309) is broken.
3.0 (2015-10-04)¶
Python 3 support (3.3 / 3.4 / 3.5).
Remove support for Python 2.6 and lower.
Full unicode support in the bootloader (#824, #1224, #1323, #1340, #1396)
(Windows) Python 2.7 apps can now run from paths with non-ASCII characters
(Windows) Python 2.7 onefile apps can now run for users whose usernames contain non-ASCII characters
Fix
sys.getfilesystemencoding()
to return correct values (#446, #885).
(OSX) Executables built with PyInstaller under OS X can now be digitally signed.
(OSX) 32bit precompiled bootloader no longer distributed, only 64bit.
(Windows) for 32bit bootloader enable flag LARGEADDRESSAWARE that allows to use 4GB of RAM.
New hooks: amazon-product-api, appy, certifi, countrycode, cryptography, gi, httplib2, jsonschema, keyring, lensfunpy, mpl_toolkits.basemap, ncclient, netCDF4, OpenCV, osgeo, patsy, PsychoPy, pycountry, pycparser, PyExcelerate, PyGobject, pymssql, PyNaCl, PySiDe.QtCore, PySide.QtGui, rawpy, requests, scapy, scipy, six, SpeechRecognition, u1db, weasyprint, Xlib.
Hook fixes: babel, ctypes, django, IPython, pint, PyEnchant, Pygments, PyQt5, PySide, pyusb, sphinx, sqlalchemy, tkinter, wxPython.
Add support for automatically including data files from eggs.
Add support for directory eggs support.
Add support for all kind of namespace packages e.g.
zope.interface
, PEP302 (#502, #615, #665, #1346).Add support for
pkgutil.extend_path()
.New option
--key
to obfuscate the Python bytecode.New option
--exclude-module
to ignore a specific module or package.(Windows) New option
--uac-admin
to request admin permissions before starting the app.(Windows) New option
--uac-uiaccess
allows an elevated application to work with Remote Desktop.(Windows) New options for Side-by-side Assembly searching:
--win-private-assemblies
bundled Shared Assemblies into the application will be changed into Private Assemblies--win-no-prefer-redirects
while searching for Assemblies PyInstaller will prefer not to follow policies that redirect to newer versions.
(OSX) New option
--osx-bundle-identifier
to set .app bundle identifier.(Windows) Remove old COM server support.
Allow override PyInstaller default config directory by environment variable
PYINSTALLER_CONFIG_DIR
.Add FreeBSD support.
AIX fixes.
Solaris fixes.
Use library modulegraph for module dependency analysis.
Bootloader debug messages
LOADER: ...
printed to stderr.PyInstaller no longer extends
sys.path
and bundled 3rd-party libraries do not interfere with their other versions.Enhancemants to
Analysis()
:New arguments
excludedimports
to exclude Python modules in import hooks.New argument
binaries
to bundle dynamic libraries in .spec file and in import hooks.New argument
datas
to bundle additional data files in .spec file and in import hooks.
A lot of internal code refactoring.
Test suite migrated to pytest framework.
Improved testing infrastructure with continuous integration (Travis - Linux, Appveyor - Windows)
Wiki and bug tracker migrated to github.
Known Issues
Apps built with Windows 10 and Python 3.5 may not run on Windows versions earlier than 10 (#1566).
The multipackage (MERGE) feature (#1527) is currenty broken.
(OSX) Support for OpenDocument events (#1309) is broken.
Changelog for PyInstaller 2.x¶
2.1 (2013-09-27)¶
Rewritten manual explaining even very basic topics.
PyInstaller integration with setuptools (direct installation with easy_install or pip from PYPI - https://pypi.python.org/pypi). After installation there will be available command ‘pyinstaller’ for PyInstaller usage.
(Windows) Alter –version-file resource format to allow unicode support.
(Windows) Fix running frozen app running from paths containing foreign characters.
(Windows) Fix running PyInstaller from paths containing foreign characters.
(OSX) Implement –icon option for the .app bundles.
(OSX) Add argv emulation for OpenDocument AppleEvent (see manual for details).
Rename –buildpath to –workpath.
Created app is put to –distpath.
All temporary work files are now put to –workpath.
Add option –clean to remove PyInstaller cache and temporary files.
Add experimental support for Linux arm.
Minimum suported Python version is 2.4.
Add import hooks for docutils, jinja2, sphinx, pytz, idlelib, sqlite3.
Add import hooks for IPython, Scipy, pygst, Python for .NET.
Add import hooks for PyQt5, Bacon, raven.
Fix django import hook to work with Django 1.4.
Add rthook for twisted, pygst.
Add rthook for pkg_resource. It fixes the following functions for frozen app pkg_resources.resource_stream(), pkg_resources.resource_string().
Better support for pkg_resources (.egg manipulation) in frozen executables.
Add option –runtime-hook to allow running custom code from frozen app before loading other Python from the frozen app. This is usefull for some specialized preprocessing just for the frozen executable. E.g. this option can be used to set SIP api v2 for PyQt4.
Fix runtime option –Wignore.
Rename utils to lowercase: archieve_viewer.py, bindepend.py, build.py, grab_version.py, make_comserver.py, makespec.py, set_version.py.
(OSX) Fix missing qt_menu.nib in dist directory when using PySide.
(OSX) Fix bootloader compatibility with Mac OS X 10.5
(OSX) Search libpython in DYLD_LIBRARY_PATH if libpython cannot be found.
(OSX) Fix Python library search in virtualenv.
Environment variable PYTHONHOME is now unset and path to python home is set in bootloader by function Py_SetPythonHome().This overrides sys.prefix and sys.exec_prefix for frozen application.
Python library filename (e.g. python27.dll, libpython2.7.so.1.0, etc) is embedded to the created exe file. Bootloader is not trying several filenames anymore.
Frozen executables now use PEP-302 import hooks to import frozen modules and C extensions. (sys.meta_path)
Drop old import machinery from iu.py.
Drop own code to import modules from zip archives (.egg files) in frozen executales. Native Python implementation is kept unchanged.
Drop old crypto code. This feature was never completed.
Drop bootloader dependency on Python headers for compilation.
(Windows) Recompile bootloaders with VS2008 to ensure win2k compatibility.
(Windows) Use 8.3 filenames for homepath/temppath.
Add prefix LOADER to the debug text from bootloader.
Allow running PyInstaller programatically.
Move/Rename some files, code refactoring.
Add more tests.
Tilde is in PyInstaller recognized as $HOME variable.
2.0 (2012-08-08)¶
Minimum suported Python version is 2.3.
(OSX) Add support for Mac OS X 64-bit
(OSX) Add support Mac OS X 10.7 (Lion) and 10.8 (Mountain Lion).
(OSX) With argument –windowed PyInstaller creates application bundle (.app)
automatically.
Add experimental support for AIX (thanks to Martin Gamwell Dawids).
Add experimental support for Solaris (thanks to Hywel Richards).
Add Multipackage function to create a collection of packages to avoid
library duplication. See documentation for more details.
New symplified command line interface. Configure.py/Makespec.py/Build.py
replaced by pyinstaller.py. See documentation for more details.
Removed cross-building/bundling feature which was never really finished.
Added option –log-level to all scripts to adjust level of output (thanks to Hartmut Goebel).
rthooks.dat moved to support/rthooks.dat
Packaged executable now returns the same return-code as the
unpackaged script (thanks to Brandyn White).
Add import hook for PyUSB (thanks to Chien-An “Zero” Cho).
Add import hook for wx.lib.pubsub (thanks to Daniel Hyams).
Add import hook for pyttsx.
Improve import hook for Tkinter.
Improve import hook for PyQt4.
Improve import hook for win32com.
Improve support for running PyInstaller in virtualenv.
Add cli options –additional-hooks-dir and –hidden-import.
Remove cli options -X, -K, -C, –upx, –tk, –configfile, –skip-configure.
UPX is used by default if available in the PATH variable.
Remove compatibility code for old platforms (dos, os2, MacOS 9).
Use Python logging system for message output (thanks to Hartmut Goebel).
Environment variable MEIPASS2 is accessible as sys._MEIPASS.
Bootloader now overrides PYTHONHOME and PYTHONPATH. PYTHONHOME and PYTHONPATH is set to the value of MEIPASS2 variable.
Bootloader uses absolute paths.
(OSX) Drop dependency on otool from Xcode on Mac OSX.
(OSX) Fix missing qt_menu.nib in dist directory when using PyQt4.
(OSX) Bootloader does not use DYLD_LIBRARY_PATH on Mac OS X anymore. @loader_path is used instead.
(OSX) Add support to detect .dylib dependencies on Mac OS X containing @executable_path, @loader_path and @rpath.
(OSX) Use macholib to detect dependencies on dynamic libraries.
Improve test suite.
Improve source code structure.
Replace os.system() calls by suprocess module.
Bundle fake ‘site’ module with frozen applications to prevent loading any user’s Python modules from host OS.
Include runtime hooks (rthooks) in code analysis.
Source code hosting moved to github: https://github.com/pyinstaller/pyinstaller
Hosting for running tests daily: https://jenkins.shiningpanda-ci.com/pyinstaller/
Changelog for PyInstaller 1.x¶
1.5.1 (2011-08-01)¶
New default PyInstaller icon for generated executables on Windows.
Add support for Python built with –enable-shared on Mac OSX.
Add requirements section to documentation.
Documentation is now generated by rst2html and rst2pdf.
Fix wrong path separators for bootloader-file on Windows
Add workaround for incorrect platform.system() on some Python Windows installation where this function returns ‘Microsoft’ instead ‘Windows’.
Fix –windowed option for Mac OSX where a console executable was created every time even with this option.
Mention dependency on otool, ldd and objdump in documentation.
Fix typo preventing detection of DLL libraries loaded by ctypes module.
1.5 (2011-05-05)¶
Full support for Python 2.7.
Full support for Python 2.6 on Windows. No manual redistribution of DLLs, CRT, manifest, etc. is required: PyInstaller is able to bundle all required dependencies (thanks to Florian Hoech).
Added support for Windows 64-bit (thanks to Martin Zibricky).
Added binary bootloaders for Linux (32-bit and 64-bit, using LSB), and Darwin (32-bit). This means that PyInstaller users on this platform don’t need to compile the bootloader themselves anymore (thanks to Martin Zibricky and Lorenzo Mancini).
Rewritten the build system for the bootloader using waf (thanks to Martin Zibricky)
Correctly detect Python unified binary under Mac OSX, and bail out if the unsupported 64-bit version is used (thanks to Nathan Weston).
Fix TkInter support under Mac OSX (thanks to Lorenzo Mancini).
Improve bundle creation under Mac OSX and correctly support also one-dir builds within bundles (thanks to Lorenzo Mancini).
Fix spurious KeyError when using dbhash
Fix import of nested packages made from Pyrex-generated files.
PyInstaller is now able to follow dependencies of binary extensions (.pyd/.so) compressed within .egg-files.
Add import hook for PyTables.
Add missing import hook for QtWebKit.
Add import hook for pywinauto.
Add import hook for reportlab (thanks Nevar).
Improve matplotlib import hook (for Mac OSX).
Improve Django import hooks.
Improve compatibility across multiple Linux distributions by being more careful on which libraries are included/excluded in the package.
Improve compatibility with older Python versions (Python 2.2+).
Fix double-bouncing-icon bug on Mac OSX. Now windowed applications correctly start on Mac OSX showing a single bouncing icon.
Fix weird “missing symbol” errors under Mac OSX (thanks to Isaac Wagner).
1.4 (2010-03-22)¶
Fully support up to Python 2.6 on Linux/Mac and Python 2.5 on Windows.
Preliminar Mac OSX support: both one-file and one-dir is supported; for non-console applications, a bundle can be created. Thanks to many people that worked on this across several months (Daniele Zannotti, Matteo Bertini, Lorenzo Mancini).
Improved Linux support: generated executables are fatter but now should now run on many different Linux distributions (thanks to David Mugnai).
Add support for specifying data files in import hooks. PyInstaller can now automatically bundle all data files or plugins required for a certain 3rd-party package.
Add intelligent support for ctypes: PyInstaller is now able to track all places in the source code where ctypes is used and automatically bundle dynamic libraries accessed through ctypes. (Thanks to Lorenzo Mancini for submitting this). This is very useful when using ctypes with custom-made dynamic libraries.
Executables built with PyInstaller under Windows can now be digitally signed.
Add support for absolute imports in Python 2.5+ (thanks to Arve Knudsen).
Add support for relative imports in Python 2.5+.
Add support for cross-compilation: PyInstaller is now able to build Windows executables when running under Linux. See documentation for more details.
Add support for .egg files: PyInstaller is now able to look for dependencies within .egg files, bundle them and make them available at runtime with all the standard features (entry-points, etc.).
Add partial support for .egg directories: PyInstaller will treat them as normal packages and thus it will not bundle metadata.
Under Linux/Mac, it is now possible to build an executable even when a system packages does not have .pyc or .pyo files available and the system-directory can be written only by root. PyInstaller will in fact generate the required .pyc/.pyo files on-the-fly within a build-temporary directory.
Add automatic import hooks for many third-party packages, including:
PyQt4 (thanks to Pascal Veret), with complete plugin support.
pyodbc (thanks to Don Dwiggins)
cElementTree (both native version and Python 2.5 version)
lxml
SQLAlchemy (thanks to Greg Copeland)
email in Python 2.5 (though it does not support the old-style Python 2.4 syntax with Python 2.5)
gadfly
PyQWt5
mako
Improved PyGTK (thanks to Marco Bonifazi and foxx).
paste (thanks to Jamie Kirkpatrick)
matplotlib
Add fix for the very annoying “MSVCRT71 could not be extracted” bug, which was caused by the DLL being packaged twice (thanks to Idris Aykun).
Removed C++-style comments from the bootloader for compatibility with the AIX compiler.
Fix support for .py files with DOS line endings under Linux (fixes PyOpenGL).
Fix support for PIL when imported without top-level package (“import Image”).
Fix PyXML import hook under NT (thanks to Lorenzo Mancini)
Fixed problem with PyInstaller picking up the wrong copy of optparse.
Improve correctness of the binary cache of UPX’d/strip’d files. This fixes problems when switching between multiple versions of the same third-party library (like e.g. wxPython allows to do).
Fix a stupid bug with modules importing optparse (under Linux) (thanks to Louai Al-Khanji).
Under Python 2.4+, if an exception is raised while importing a module inside a package, the module is now removed from the parent’s namespace (to match the behaviour of Python itself).
Fix random race-condition at startup of one-file packages, that was causing this exception to be generated: “PYZ entry ‘encodings’ (0j) is not a valid code object”.
Fix problem when having unicode strings among path elements.
Fix random exception (“bad file descriptor”) with “prints” in non-console mode (actually a pythonw “bug” that’s fixed in Python 3.0).
Sometimes the temporary directory did not get removed upon program exit, when running on Linux.
Fixed random segfaults at startup on 64-bit platforms (like x86-64).
1.3 (2006-12-20)¶
Fix bug with user-provided icons disappearing from built executables when these were compressed with UPX.
Fix problems with packaging of applications using PIL (that was broken because of a bug in Python’s import machinery, in recent Python versions). Also add a workaround including Tcl/Tk with PIL unless ImageTk is imported.
(Windows) When used under Windows XP, packaged programs now have the correct look & feel and follow user’s themes (thanks to the manifest file being linked within the generated executable). This is especially useful for applications using wxPython.
Fix a buffer overrun in the bootloader (which could lead to a crash) when the built executable is run from within a deep directory (more than 70-80 characters in the pathname).
Bootstrap modules are now compressed in the executable (so that they are not visible in plaintext by just looking at it with a hex editor).
Fixed a regression introduced in 1.1: under Linux, the bootloader does not depend on libpythonX.X.so anymore.
1.2 (2006-06-29)¶
Fix a crash when invoking UPX with certain kinds of builds.
Fix icon support by re-adding a resource section in the bootloader executable.
1.1 (2006-02-13)¶
(Windows) Make single-file packages not depend on MSVCRT71.DLL anymore, even under Python 2.4. You can eventually ship your programs really as single-file executables, even when using the newest Python version!
Fix problem with incorrect python path detection. Now using helpers from distutils.
Fix problem with rare encodings introduced in newer Python versions: now all the encodings are automatically found and included, so this problem should be gone forever.
Fix building of COM servers (was broken in 1.0 because of the new build system).
Mimic Python 2.4 behaviour with broken imports: sys.modules is cleaned up afterwise. This allows to package SQLObject applications under Windows with Python 2.4 and above.
Add import hook for the following packages:
GTK
PyOpenGL (tested 2.0.1.09)
dsnpython (tested 1.3.4)
KInterasDB (courtesy of Eugene Prigorodov)
Fix packaging of code using “time.strptime” under Python 2.3+.
(Linux) Ignore linux-gate.so while calculating dependencies (fix provided by Vikram Aggarwal).
(Windows) With Python 2.4, setup UPX properly so to be able to compress binaries generated with Visual Studio .NET 2003 (such as most of the extensions). UPX 1.92+ is needed for this.
1.0 (2005-09-19) with respect to McMillan’s Python Installer 5b5¶
Add support for Python 2.3 (fix packaging of codecs).
Add support for Python 2.4 (under Windows, needed to recompiled the bootloader with a different compiler version).
Fix support for Python 1.5.2, should be fully functional now (required to rewrite some parts of the string module for the bootloader).
Fix a rare bug in extracting the dependencies of a DLL (bug in PE header parser).
Fix packaging of PyQt programs (needed an import hook for a hidden import).
Fix imports calculation for modules using the “from __init__ import” syntax.
Fix a packaging bug when a module was being import both through binary dependency and direct import.
Restyle documentation (now using docutils and reStructuredText).
New Windows build system for automatic compilations of bootloader in all the required flavours (using Scons)
Credits¶
Thanks goes to all the kind PyInstaller contributors who have contributed new code, bug reports, fixes, comments and ideas. A brief list follows, please let us know if your name is omitted by accident:
Contributions to PyInstaller 4.9¶
Rok Mandeljc - Core Developer
Brénainn Woodsend - Core Developer
Jasper Harrison - Core Develop, Maintainer, Release Manager
gentlegiantJGC
Contributions to PyInstaller 4.8¶
Rok Mandeljc - Core Developer
Jasper Harrison - Core Develop, Maintainer, Release Manager
Brénainn Woodsend - Core Developer
Ankith, Safihre, luc-x41
Contributions to PyInstaller 4.7¶
Rok Mandeljc - Core Developer
Brénainn Woodsend - Core Developer
Jasper Harrison - Core Develop, Maintainer, Release Manager
Contributions to PyInstaller 4.6¶
Rok Mandeljc - Core Developer
Brénainn Woodsend - Core Developer
Jasper Harrison - Maintainer, Release Manager
Anssi Alahutta, Dan Yeaw, Eric Missimer, Chris Hillery, Melvin Wang, wangling12, eric15342335
Contributions to PyInstaller 4.5.1¶
Jasper Harrison - Maintainer, Release Manager
ankith26
Contributions to PyInstaller 4.5¶
Rok Mandeljc - Core Developer
Brénainn Woodsend - Core Developer
Jasper Harrison - Maintainer, Release Manager
Dave Dykstra
Andy Hobbs
Nicholas Ollinger
Contributions to PyInstaller 4.4¶
Rok Mandeljc - Core Developer
Brénainn Woodsend - Core Developer
Jasper Harrison - Core Developer, Maintainer, Release Manager
Hartmut Goebel - Core Developer
xoviat
Chrisg2000
Alex Gembe, James Duley, Jeffrey, Kenny Huynh, Maxim Mazurok, mozbugbox
Contributions to PyInstaller 4.3¶
Rok Mandeljc - Core Developer
Brénainn Woodsend - Core Developer
Jasper Harrison (Legorooj) - Core Developer, Maintainer, Release Manager
Hartmut Goebel, Core Developer, Maintainer
xoviat
Dan Yeaw, Bruno Oliveira, Maxim Kalinchenko, Max Mäusezahl, Olivier FAURAX, richardsheridan, memo-off
Contributions to PyInstaller 4.2¶
Rok Mandeljc
Hartmut Goebel - Core developer, maintainer and release manager.
Legorooj - Core developer.
Bryan A. Jones - Core developer and PyQt5-tamer.
Mickaël Schoentgen
Brénainn Woodsend
Damien Elmes, Dan Yeaw, hdf, Diggy, Filip Gospodinov, Kyle Altendorf, Matt Simpson, Nathan Summers, Phoenix, Starbuck5, Tom Hu, rockwalrus
Contributions to PyInstaller 4.1¶
Hartmut Goebel - Core developer, maintainer and release manager.
Legorooj - Core developer.
Bryan A. Jones - Core developer and PyQt5-tamer.
Rok Mandeljc
Mickaël Schoentgen
Brénainn Woodsend
Aaron Althauser, Alex, Andrew Nelson, Benedikt Brückmann, Brénainn Woodsend, Calin Culianu, Dan Yeaw, Ievgen Popovych, Loïc Messal, Łukasz Stolcman, Matt, Mohamed, Petrus, Riz, Riz Syed, Santi Santichaivekin, Sid Gupta, Victor Stinner, byehack, dcgloe, johnthagen, ozelikov,
Contributions to PyInstaller 4.0¶
Hartmut Goebel - Core developer, maintainer and release manager.
Legorooj - Core developer.
Bryan A. Jones - Core developer and PyQt5-tamer.
M Felt aka aixtools, jonnyhsu, Corey Dexter, Rok Mandeljc, Dan Yeaw, Florian Baumann, Ievgen Popovych, Ram Rachum, coreydexter, AndCycle, Dan Cutright, David Kiliani, David Maiden Mueller, FeralRobot, Frederico, Ilya Orson, ItsCinnabar, Juan Sotomayor, Matt M, Matteo Bertini, Michael Felt, Mohamed Feddad, Nehal J Wani, Or Groman, Sebastian Hohmann, Vaclav Dvorak, Ville Ilvonen, bwoodsend, eldadr, jeremyd2019, kraptor, seedgou.
Contributions to PyInstaller 3.6¶
Hartmut Goebel - Core developer, maintainer and release manager.
Bryan A. Jones - Core developer and PyQt5-tamer.
Dan Yeaw, Amir Rossert, Hugo Martins, Felix Schwarz, Giuseppe Corbelli, HoLuLuLu, Jonathan Springer, Matt Khan, Min’an, Oracizan, Victor Stinner, Andres, Andrew Chow, Bernát Gábor, Charles Duffy, Chris, Chrisg2000, FranzPio, Lee Jeonghun, Lukasz Stolcman, Lyux, László Kiss Kollár, Mathias Lohne, Michael Felt, Noodle-Head, Ogi Moore, Patryk, RedFantom, Rémy Roy, Sean McGuire, Thomas Robitaille, Tim, Toby, Tuomo, V.Shkaberda, Vojtěch Drábek, Wilmar den Ouden, david, ethframe, lnv42, ripdog, satvidh, thisisivanfong
Contributions to PyInstaller 3.5¶
Hartmut Goebel - Core developer, maintainer and release manager.
Bryan A. Jones - Core developer and PyQt5-tamer.
Dave Cortesi, Kuisong Tong, melvyn2, Giuseppe Corbelli, Florian Bruhin, Amir Ramezani, Cesar Vandevelde, Paul Müller, Thomas Robitaille, zachbateman, Addison Elliott, Amir Rossert, AndCycle, Atomfighter10101, Chris Berthiaume, Craig Younkins (bot), Don Krueger, Edward Chen, Exane Server Team, Hannes, Iwan, Jakob Schnitzer, Janzert, Jendrik Seipp, Jonathan Springer, Kirill German, Laszlo Kiss-Kollar, Loran425, Lori J, M*C*O, Nikita Melentev, Peter Bittner, RedFantom, Roman, Roman Yurchak, Ruslan Kuprieiev, Spencer Brown, Suzumizaki, Tobias Gruetzmacher, Tobias V. Langhoff, TobiasRzepka, Tom Hacohen, Yuval Shkolar, cclauss, charlesoblack, djl197, matias morant, satejkhedekar, zhu
Contributions to PyInstaller 3.4¶
Hartmut Goebel - Core developer, maintainer and release manager.
Bryan A. Jones - Core developer and PyQt5-tamer.
David Vierra - Core developer and encoding specialist.
xoviat - brave contributor
Hugo vk - brave contributor
Mickaël Schoentgen, Charles Nicholson, Jonathan Springer, Benoît Vinot, Brett Higgins, Dustin Spicuzza, Marco Nenciarini, Aaron Hampton, Cody Scot, Dave Cortesi, Helder Eijs, Innokenty Lebedev, Joshua Klein, Matthew Clapp, Misha Turnbull, ethframe, Amir Ramezani, Arthur Silva, Blue, Craig MacEachern, Cédric RICARD, Fredrik Ahlberg, Glenn Ramsey, Jack Mordaunt, Johann Bauer, Joseph Heck, Kyle Stewart, Lev Maximov, Luo Shawn, Marco Nenciarini, Mario Costa, Matt Reynolds, Matthieu Gautier, Michael Herrmann, Moritz Kassner, Natanael Arndt, Nejc Habjan, Paweł Kowalik, Pedro de Medeiros, Peter Conerly, Peter Würtz, Rémy Roy, Saurabh Yadav, Siva Prasad, Steve Peak, Steven M. Vascellaro, Steven M. Vascellaro, Suzumizaki-Kimitaka, ThomasV, Timothée Lecomte, Torsten Sommer, Weliton Freitas, Zhen Zhang, dimitriepirghie, lneuhaus, s3goat, satarsa,
Contributions to PyInstaller 3.3.1¶
Hartmut Goebel - Core developer and release manager.
Bryan A. Jones - Core developer.
David Vierra - Core developer and encoding specialist.
xoviat - brave contributor
Dave Cortesi, David Hoese, John Daytona, Nejc Habjan, Addison Elliott, Bharath Upadhya, Bill Dengler, Chris Norman, Miles Erickson, Nick Dimou, Thomas Waldmann, David Weil, Placinta
Contributions to PyInstaller 3.3¶
Special Thanks xiovat for implementing Python3.6 support and to Jonathan Springer and xoviat for stabilizing the continuous integration tests.
Hartmut Goebel - Core developer and release manager.
Bryan A. Jones - Core developer.
David Vierra - Core developer and encoding specialist.
xoviat - brave programmer
Jonathan Springer
Vito Kortbeek
Dustin Spicuzza
Ben Hagen
Paavo
Brian Teague
Chris Norman
Jonathan Stewmon
Guillaume Thiolliere
Justin Harris
Kenneth Zhao
Paul Müller
giumas
y2kbugger
肖寅东
Adam Clark, AndCycle, Andreas Schiefer, Arthur Silva, Aswa Paul, Bharath Upadhya, Brian Teague, Charles Duffy, Chris Coutinho, Cody Scott, Czarek Tomczak, Dang Mai, Daniel Hyams, David Hoese, Eelco van Vliet, Eric Drechsel, Erik Bjäreholt, Hatem AlSum, Henry Senyondo, Jan Čapek, Jeremy T. Hetzel, Jonathan Dan, Julie Marchant, Luke Lee, Marc Abramowitz, Matt Wilkie, Matthew Einhorn, Michael Herrmann, Niklas Rosenstein, Philippe Ombredanne, Piotr Radkowski, Ronald Oussoren, Ruslan Kuprieiev, Segev Finer, Shengjing Zhu 朱晟菁, Steve, Steven Noonan, Tibor Csonka, Till Bey, Tobias Gruetzmacher, 陳鵬宇 (float)
Contributions to PyInstaller 3.2.1¶
Special Thanks to Thomas Waldmann and David Vierra for support when working on the new build system.
Hartmut Goebel - Core developer and release manager.
Martin Zibricky - Core developer.
David Cortesi - Core developer and documentation manager.
Bryan A. Jones - Core developer.
David Vierra - Core developer and encoding specialist.
Cecil Curry - brave bug-fixing and code-refactoring
Amane Suzuki
Andy Cycle
Axel Huebl
Bruno Oliveira
Dan Auerbach
Daniel Hyams
Denis Akhiyarov
Dror Asaf
Dustin Spicuzza
Emanuele Bertoldi
Glenn Ramsey
Hugh Dowling
Jesse Suen
Jonathan Dan
Jonathan Springer
Jonathan Stewmon
Julie Marchant
Kenneth Zhao
Linus Groh
Mansour Moufid
Martin Zibricky
Matteo Bertini
Nicolas Dickreuter
Peter Würtz
Ronald Oussoren
Santiago Reig
Sean Fisk
Sergei Litvinchuk
Stephen Rauch
Thomas Waldmann
Till Bald
xoviat
Contributions to PyInstaller 3.2¶
Hartmut Goebel - Core developer and release manager.
Martin Zibricky - Core developer.
David Cortesi - Core developer and documentation manager.
Bryan A. Jones - Core developer.
David Vierra - Core developer and encoding specialist.
Cecil Curry - brave bug-fixing and code-refactoring
And Cycle - unicode fixes.
Chris Hager - QtQuick hook.
David Schoorisse - wrong icon paramter in Windows example.
Florian Bruhin - typo hunting.
Garth Bushell - Support for objcopy.
Insoleet - lib2to3 hook
Jonathan Springer - hook fixes, brave works on PyQt.
Matteo Bertini - code refactoring.
Jonathan Stewmon - bug hunting.
Kenneth Zhao - waf update.
Leonid Rozenberg - typo hunting.
Merlijn Wajer - bug fixing.
Nicholas Chammas - cleanups.
nih - hook fixes.
Olli-Pekka Heinisuo - CherryPy hook.
Rui Carmo - cygwin fixes.
Stephen Rauch - hooks and fixes for unnecessary rebuilds.
Tim Stumbaugh - bug hunting.
Contributions to PyInstaller 3.1.1¶
Hartmut Goebel - Core developer and release manager.
David Vierra - Core developer and encoding specialist.
Torsten Landschoff - Fix problems with setuptools
Peter Inglesby - resolve symlinks in modulegraph.py
syradium - bug hunting
dessant - bug hunting
Joker Qyou - bug hunting
Contributions to PyInstaller 3.1¶
Hartmut Goebel - Core developer and release manager.
Martin Zibricky - Core developer.
David Cortesi - Core developer and documentation manager.
Bryan A. Jones - Core developer.
David Vierra - Core developer and encoding specialist.
Andrei Kopats - Windows fixes.
Andrey Malkov - Django runtime hooks.
Ben Hagen - kivy hook, GStreamer realtime hook.
Cecil Curry - Module Version Comparisons and and reworking hooks.
Dustin Spicuzza - Hooks for GLib, GIntrospection, Gstreamer, etc.
giumas - lxml.isoschematron hook.
Jonathan Stewmon - Hooks for botocore, boto, boto3 and gevent.monkey.
Kenneth Zhao - Solaris fixes.
Matthew Einhorn - kivy hook.
mementum - pubsub.core hook.
Nicholas Chammas - Documentation updates.
Nico Galoppo - Hooks for skimage and sklearn.
Panagiotis H.M. Issaris - weasyprint hook.
Penaz - shelve hook.
Roman Yurchak - scipy.linalg hook.
Starwarsfan2099 - Distorm3 hook.
Thomas Waldmann - Fixes for Bootloader and FreeBSD.
Tim Stumbaugh - Bug fixes.
zpin - Bug fixes.
Contributions to PyInstaller 3.0¶
Martin Zibricky - Core developer and release manager.
Hartmut Goebel - Core developer.
David Cortesi - Initial work on Python 3 support, Python 3 fixes, documentation updates, various hook fixes.
Cecil Curry - ‘six’ hook for Python 3, various modulegraph improvements, wxPython hook fixes,
David Vierra - unicode support in bootloader, Windows SxS Assembly Manifest fixes and many other Windows improvements.
Michael Mulley - keyring, PyNaCl import hook.
Rainer Dreyer - OS X fixes, hook fixes.
Bryan A. Jones - test suite fixes, various hook fixes.
Philippe Pepiot - Linux fixes.
Emanuele Bertoldi - pycountry import hook, Django import hook fixes.
Glenn Ramsey - PyQt5 import hook - support for QtWebEngine on OSX, various hook fixes, Windows fixes.
Karol Woźniak - import hook fixes.
Jonathan Springer - PyGObject hooks. ctypes, PyEnchant hook fixes, OS X fixes.
Giuseppe Masetti - osgeo, mpl_toolkits.basemap and netCDF4 import hooks.
Yuu Yamashita - OS X fixes.
Thomas Waldmann - FreeBSD fixes.
Boris Savelev - FreeBSD and Solaris fixes.
Guillermo Gutiérrez - Python 3 fixes.
Jasper Geurtz - gui fixes, hook fixes.
Holger Pandel - Windows fixes.
Anthony Zhang - SpeechRecognition import hook.
Andrei Fokau - Python 3.5 fixes.
Kenneth Zhao - AIX fixes.
Maik Riechert - lensfunpy, rawpy import hooks.
Tim Stumbaugh - hook fixes.
Andrew Leech - Windows fixes.
Patrick Robertson - tkinter import hook fixes.
Yaron de Leeuw - import hook fixes.
Bryan Cort - PsychoPy import hook.
Phoebus Veiz - bootloader fixes.
Sean Johnston - version fix.
Kevin Zhang - PyExcelerate import hook.
Paulo Matias - unicode fixes.
Lorenzo Villani - crypto feature, various fixes.
Janusz Skonieczny - hook fixes.
Martin Gamwell Dawids - Solaris fixes.
Volodymyr Vitvitskyi - typo fixes.
Thomas Kho - django import hook fixes.
Konstantinos Koukopoulos - FreeBSD support.
Jonathan Beezley - PyQt5 import hook fixes.
Andraz Vrhovec - various fixes.
Noah Treuhaft - OpenCV import hook.
Michael Hipp - reportlab import hook.
Michael Sverdlik - certifi, httplib2, requests, jsonschema import hooks.
Santiago Reig - appy import hook.
Contributions to PyInstaller 2.1 and older¶
Glenn Ramsey - PyQt5 import hook.
David Cortesi - PyInstaller manual rewrite.
Vaclav Smilauer - IPython import hook.
Shane Hansen - Linux arm support.
Bryan A. Jones - docutils, jinja2, sphinx, pytz, idlelib import hooks.
Patrick Stewart <patstew at gmail dot com> - scipy import hook.
Georg Schoelly <mail at georg-schoelly dot com> - storm ORM import hook.
Vinay Sajip - zmq import hook.
Martin Gamwell Dawids - AIX support.
Hywel Richards - Solaris support.
Brandyn White - packaged executable return code fix.
Chien-An “Zero” Cho - PyUSB import hook.
Daniel Hyams - h2py, wx.lib.pubsub import hooks.
Hartmut Goebel - Python logging system for message output. Option –log-level.
Florian Hoech - full Python 2.6 support on Windows including automatic handling of DLLs, CRT, manifest, etc. Read and write resources from/to Win32 PE files.
Martin Zibricky - rewrite the build system for the bootloader using waf. LSB compliant precompiled bootloaders for Linux. Windows 64-bit support.
Peter Burgers - matplotlib import hook.
Nathan Weston - Python architecture detection on OS X.
Isaac Wagner - various OS X fixes.
Matteo Bertini - OS X support.
Daniele Zannotti - OS X support.
David Mugnai - Linux support improvements.
Arve Knudsen - absolute imports in Python 2.5+
Pascal Veret - PyQt4 import hook with Qt4 plugins.
Don Dwiggins - pyodbc import hook.
Allan Green - refactoring and improved in-process COM servers.
Daniele Varrazzo - various bootloader and OS X fixes.
Greg Copeland - sqlalchemy import hook.
Seth Remington - PyGTK hook improvements.
Marco Bonifazi - PyGTK hook improvements. PyOpenGL import hook.
Jamie Kirkpatrick - paste import hook.
Lorenzo Mancini - PyXML import hook fixes under Windows. OS X support. App bundle creation on OS X. Tkinter on OS X. Precompiled bootloaders for OS X.
Lorenzo Berni - django import hook.
Louai Al-Khanji - fixes with optparse module.
Thomas Heller - set custom icon of Windows exe files.
Eugene Prigorodov <eprigorodov at naumen dot ru> - KInterasDB import hook.
David C. Morrill - vtkpython import hook.
Alan James Salmoni - Tkinter interface to PyInstaller.
Man Pages¶
pyinstaller¶
DESCRIPTION¶
PyInstaller is a program that freezes (packages) Python programs into stand-alone executables, under Windows, GNU/Linux, Mac OS X, FreeBSD, OpenBSD, Solaris and AIX. Its main advantages over similar tools are that PyInstaller works with Python 3.6-3.9, it builds smaller executables thanks to transparent compression, it is fully multi-platform, and use the OS support to load the dynamic libraries, thus ensuring full compatibility.
You may either pass one or more file-names of Python scripts or a single
.spec-file-name. In the first case, pyinstaller
will generate a
.spec-file (as pyi-makespec
would do) and immediately process it.
If you pass a .spec-file, this will be processed and most options given on the command-line will have no effect. Please see the PyInstaller Manual for more information.
OPTIONS¶
Positional Arguments¶
scriptname
Name of scriptfiles to be processed or exactly one .spec file. If a .spec file is specified, most options are unnecessary and are ignored.
Optional Arguments¶
- -h, --help
show this help message and exit
- -v, --version
Show program version info and exit.
- --distpath DIR
Where to put the bundled app (default: ./dist)
- --workpath WORKPATH
Where to put all the temporary work files, .log, .pyz and etc. (default: ./build)
- -y, --noconfirm
Replace output directory (default: SPECPATH/dist/SPECNAME) without asking for confirmation
- --upx-dir UPX_DIR
Path to UPX utility (default: search the execution path)
- -a, --ascii
Do not include unicode encoding support (default: included if available)
- --clean
Clean PyInstaller cache and remove temporary files before building.
- --log-level LEVEL
Amount of detail in build-time console messages. LEVEL may be one of TRACE, DEBUG, INFO, WARN, ERROR, CRITICAL (default: INFO).
What To Generate¶
- -D, --onedir
Create a one-folder bundle containing an executable (default)
- -F, --onefile
Create a one-file bundled executable.
- --specpath DIR
Folder to store the generated spec file (default: current directory)
- -n NAME, --name NAME
Name to assign to the bundled app and spec file (default: first script’s basename)
What To Bundle, Where To Search¶
- --add-data <SRC;DEST or SRC:DEST>
Additional non-binary files or folders to be added to the executable. The path separator is platform specific,
os.pathsep
(which is;
on Windows and:
on most unix systems) is used. This option can be used multiple times.- --add-binary <SRC;DEST or SRC:DEST>
Additional binary files to be added to the executable. See the
--add-data
option for more details. This option can be used multiple times.- -p DIR, --paths DIR
A path to search for imports (like using PYTHONPATH). Multiple paths are allowed, separated by
':'
, or use this option multiple times. Equivalent to supplying thepathex
argument in the spec file.- --hidden-import MODULENAME, --hiddenimport MODULENAME
Name an import not visible in the code of the script(s). This option can be used multiple times.
- --collect-submodules MODULENAME
Collect all submodules from the specified package or module. This option can be used multiple times.
- --collect-data MODULENAME, --collect-datas MODULENAME
Collect all data from the specified package or module. This option can be used multiple times.
- --collect-binaries MODULENAME
Collect all binaries from the specified package or module. This option can be used multiple times.
- --collect-all MODULENAME
Collect all submodules, data files, and binaries from the specified package or module. This option can be used multiple times.
- --copy-metadata PACKAGENAME
Copy metadata for the specified package. This option can be used multiple times.
- --recursive-copy-metadata PACKAGENAME
Copy metadata for the specified package and all its dependencies. This option can be used multiple times.
- --additional-hooks-dir HOOKSPATH
An additional path to search for hooks. This option can be used multiple times.
- --runtime-hook RUNTIME_HOOKS
Path to a custom runtime hook file. A runtime hook is code that is bundled with the executable and is executed before any other code or module to set up special features of the runtime environment. This option can be used multiple times.
- --exclude-module EXCLUDES
Optional module or package (the Python name, not the path name) that will be ignored (as though it was not found). This option can be used multiple times.
- --key KEY
The key used to encrypt Python bytecode.
- --splash IMAGE_FILE
(EXPERIMENTAL) Add an splash screen with the image IMAGE_FILE to the application. The splash screen can display progress updates while unpacking.
How To Generate¶
-d {all,imports,bootloader,noarchive}, –debug {all,imports,bootloader,noarchive}
Provide assistance with debugging a frozen application. This argument may be provided multiple times to select several of the following options. - all: All three of the following options. - imports: specify the -v option to the underlying Python interpreter, causing it to print a message each time a module is initialized, showing the place (filename or built-in module) from which it is loaded. See https://docs.python.org/3/using/cmdline.html#id4. - bootloader: tell the bootloader to issue progress messages while initializing and starting the bundled app. Used to diagnose problems with missing imports. - noarchive: instead of storing all frozen Python source files as an archive inside the resulting executable, store them as files in the resulting output directory.
- --python-option PYTHON_OPTION
Specify a command-line option to pass to the Python interpreter at runtime. Currently supports “v” (equivalent to “–debug imports”), “u”, and “W <warning control>”.
- -s, --strip
Apply a symbol-table strip to the executable and shared libs (not recommended for Windows)
- --noupx
Do not use UPX even if it is available (works differently between Windows and *nix)
- --upx-exclude FILE
Prevent a binary from being compressed when using upx. This is typically used if upx corrupts certain binaries during compression. FILE is the filename of the binary without path. This option can be used multiple times.
Windows And Mac Os X Specific Options¶
- -c, --console, --nowindowed
Open a console window for standard i/o (default). On Windows this option has no effect if the first script is a ‘.pyw’ file.
- -w, --windowed, --noconsole
Windows and Mac OS X: do not provide a console window for standard i/o. On Mac OS this also triggers building a Mac OS .app bundle. On Windows this option is automatically set if the first script is a ‘.pyw’ file. This option is ignored on *NIX systems.
- -i <FILE.ico or FILE.exe,ID or FILE.icns or “NONE”>, --icon <FILE.ico or FILE.exe,ID or FILE.icns or “NONE”>
FILE.ico: apply the icon to a Windows executable. FILE.exe,ID: extract the icon with ID from an exe. FILE.icns: apply the icon to the .app bundle on Mac OS. Use “NONE” to not apply any icon, thereby making the OS to show some default (default: apply PyInstaller’s icon)
- --disable-windowed-traceback
Disable traceback dump of unhandled exception in windowed (noconsole) mode (Windows and macOS only), and instead display a message that this feature is disabled.
Windows Specific Options¶
- --version-file FILE
Add a version resource from FILE to the exe.
- -m <FILE or XML>, --manifest <FILE or XML>
Add manifest FILE or XML to the exe.
- --no-embed-manifest
Generate an external .exe.manifest file instead of embedding the manifest into the exe. Applicable only to onedir mode; in onefile mode, the manifest is always embedded, regardless of this option.
- -r RESOURCE, --resource RESOURCE
Add or update a resource to a Windows executable. The RESOURCE is one to four items, FILE[,TYPE[,NAME[,LANGUAGE]]]. FILE can be a data file or an exe/dll. For data files, at least TYPE and NAME must be specified. LANGUAGE defaults to 0 or may be specified as wildcard * to update all resources of the given TYPE and NAME. For exe/dll files, all resources from FILE will be added/updated to the final executable if TYPE, NAME and LANGUAGE are omitted or specified as wildcard *. This option can be used multiple times.
- --uac-admin
Using this option creates a Manifest that will request elevation upon application start.
- --uac-uiaccess
Using this option allows an elevated application to work with Remote Desktop.
Windows Side-By-Side Assembly Searching Options (Advanced)¶
- --win-private-assemblies
Any Shared Assemblies bundled into the application will be changed into Private Assemblies. This means the exact versions of these assemblies will always be used, and any newer versions installed on user machines at the system level will be ignored.
- --win-no-prefer-redirects
While searching for Shared or Private Assemblies to bundle into the application, PyInstaller will prefer not to follow policies that redirect to newer versions, and will try to bundle the exact versions of the assembly.
Mac Os Specific Options¶
- --osx-bundle-identifier BUNDLE_IDENTIFIER
Mac OS .app bundle identifier is used as the default unique program name for code signing purposes. The usual form is a hierarchical name in reverse DNS notation. For example: com.mycompany.department.appname (default: first script’s basename)
- --target-architecture ARCH, --target-arch ARCH
Target architecture (macOS only; valid values: x86_64, arm64, universal2). Enables switching between universal2 and single-arch version of frozen application (provided python installation supports the target architecture). If not target architecture is not specified, the current running architecture is targeted.
- --codesign-identity IDENTITY
Code signing identity (macOS only). Use the provided identity to sign collected binaries and generated executable. If signing identity is not provided, ad- hoc signing is performed instead.
- --osx-entitlements-file FILENAME
Entitlements file to use when code-signing the collected binaries (macOS only).
Rarely Used Special Options¶
- --runtime-tmpdir PATH
Where to extract libraries and support files in onefile-mode. If this option is given, the bootloader will ignore any temp-folder location defined by the run-time OS. The
_MEIxxxxxx
-folder will be created here. Please use this option only if you know what you are doing.- --bootloader-ignore-signals
Tell the bootloader to ignore signals rather than forwarding them to the child process. Useful in situations where for example a supervisor process signals both the bootloader and the child (e.g., via a process group) to avoid signalling the child twice.
ENVIRONMENT VARIABLES¶
- PYINSTALLER_CONFIG_DIR
This changes the directory where PyInstaller caches some files. The default location for this is operating system dependent, but is typically a subdirectory of the home directory.
SEE ALSO¶
pyi-makespec
(1),
The PyInstaller Manual https://pyinstaller.readthedocs.io/,
Project Homepage http://www.pyinstaller.org
pyi-makespec¶
SYNOPSIS¶
pyi-makespec
<options> SCRIPT [SCRIPT …]
DESCRIPTION¶
The spec file is the description of what you want PyInstaller to do
with your program. pyi-makespec
is a simple wizard to create spec
files that cover basic usages:
pyi-makespec [--onefile] yourprogram.py
By default, pyi-makespec
generates a spec file that tells
PyInstaller to create a distribution directory contains the main
executable and the dynamic libraries. The option --onefile
specifies that you want PyInstaller to build a single file with
everything inside.
In most cases the specfile generated by pyi-makespec
is all you
need. If not, see When things go wrong in the manual and be sure to
read the introduction to Spec Files.
OPTIONS¶
Positional Arguments¶
scriptname
Optional Arguments¶
- -h, --help
show this help message and exit
- --log-level LEVEL
Amount of detail in build-time console messages. LEVEL may be one of TRACE, DEBUG, INFO, WARN, ERROR, CRITICAL (default: INFO).
What To Generate¶
- -D, --onedir
Create a one-folder bundle containing an executable (default)
- -F, --onefile
Create a one-file bundled executable.
- --specpath DIR
Folder to store the generated spec file (default: current directory)
- -n NAME, --name NAME
Name to assign to the bundled app and spec file (default: first script’s basename)
What To Bundle, Where To Search¶
- --add-data <SRC;DEST or SRC:DEST>
Additional non-binary files or folders to be added to the executable. The path separator is platform specific,
os.pathsep
(which is;
on Windows and:
on most unix systems) is used. This option can be used multiple times.- --add-binary <SRC;DEST or SRC:DEST>
Additional binary files to be added to the executable. See the
--add-data
option for more details. This option can be used multiple times.- -p DIR, --paths DIR
A path to search for imports (like using PYTHONPATH). Multiple paths are allowed, separated by
':'
, or use this option multiple times. Equivalent to supplying thepathex
argument in the spec file.- --hidden-import MODULENAME, --hiddenimport MODULENAME
Name an import not visible in the code of the script(s). This option can be used multiple times.
- --collect-submodules MODULENAME
Collect all submodules from the specified package or module. This option can be used multiple times.
- --collect-data MODULENAME, --collect-datas MODULENAME
Collect all data from the specified package or module. This option can be used multiple times.
- --collect-binaries MODULENAME
Collect all binaries from the specified package or module. This option can be used multiple times.
- --collect-all MODULENAME
Collect all submodules, data files, and binaries from the specified package or module. This option can be used multiple times.
- --copy-metadata PACKAGENAME
Copy metadata for the specified package. This option can be used multiple times.
- --recursive-copy-metadata PACKAGENAME
Copy metadata for the specified package and all its dependencies. This option can be used multiple times.
- --additional-hooks-dir HOOKSPATH
An additional path to search for hooks. This option can be used multiple times.
- --runtime-hook RUNTIME_HOOKS
Path to a custom runtime hook file. A runtime hook is code that is bundled with the executable and is executed before any other code or module to set up special features of the runtime environment. This option can be used multiple times.
- --exclude-module EXCLUDES
Optional module or package (the Python name, not the path name) that will be ignored (as though it was not found). This option can be used multiple times.
- --key KEY
The key used to encrypt Python bytecode.
- --splash IMAGE_FILE
(EXPERIMENTAL) Add an splash screen with the image IMAGE_FILE to the application. The splash screen can display progress updates while unpacking.
How To Generate¶
-d {all,imports,bootloader,noarchive}, –debug {all,imports,bootloader,noarchive}
R|Provide assistance with debugging a frozen application. This argument may be provided multiple times to select several of the following options. - all: All three of the following options. - imports: specify the -v option to the underlying Python interpreter, causing it to print a message each time a module is initialized, showing the place (filename or built-in module) from which it is loaded. See https://docs.python.org/3/using/cmdline.html#id4. - bootloader: tell the bootloader to issue progress messages while initializing and starting the bundled app. Used to diagnose problems with missing imports. - noarchive: instead of storing all frozen Python source files as an archive inside the resulting executable, store them as files in the resulting output directory.
- --python-option PYTHON_OPTION
Specify a command-line option to pass to the Python interpreter at runtime. Currently supports “v” (equivalent to “–debug imports”), “u”, and “W <warning control>”.
- -s, --strip
Apply a symbol-table strip to the executable and shared libs (not recommended for Windows)
- --noupx
Do not use UPX even if it is available (works differently between Windows and *nix)
- --upx-exclude FILE
Prevent a binary from being compressed when using upx. This is typically used if upx corrupts certain binaries during compression. FILE is the filename of the binary without path. This option can be used multiple times.
Windows And Mac Os X Specific Options¶
- -c, --console, --nowindowed
Open a console window for standard i/o (default). On Windows this option has no effect if the first script is a ‘.pyw’ file.
- -w, --windowed, --noconsole
Windows and Mac OS X: do not provide a console window for standard i/o. On Mac OS this also triggers building a Mac OS .app bundle. On Windows this option is automatically set if the first script is a ‘.pyw’ file. This option is ignored on *NIX systems.
- -i <FILE.ico or FILE.exe,ID or FILE.icns or “NONE”>, --icon <FILE.ico or FILE.exe,ID or FILE.icns or “NONE”>
FILE.ico: apply the icon to a Windows executable. FILE.exe,ID: extract the icon with ID from an exe. FILE.icns: apply the icon to the .app bundle on Mac OS. Use “NONE” to not apply any icon, thereby making the OS to show some default (default: apply PyInstaller’s icon)
- --disable-windowed-traceback
Disable traceback dump of unhandled exception in windowed (noconsole) mode (Windows and macOS only), and instead display a message that this feature is disabled.
Windows Specific Options¶
- --version-file FILE
Add a version resource from FILE to the exe.
- -m <FILE or XML>, --manifest <FILE or XML>
Add manifest FILE or XML to the exe.
- --no-embed-manifest
Generate an external .exe.manifest file instead of embedding the manifest into the exe. Applicable only to onedir mode; in onefile mode, the manifest is always embedded, regardless of this option.
- -r RESOURCE, --resource RESOURCE
Add or update a resource to a Windows executable. The RESOURCE is one to four items, FILE[,TYPE[,NAME[,LANGUAGE]]]. FILE can be a data file or an exe/dll. For data files, at least TYPE and NAME must be specified. LANGUAGE defaults to 0 or may be specified as wildcard * to update all resources of the given TYPE and NAME. For exe/dll files, all resources from FILE will be added/updated to the final executable if TYPE, NAME and LANGUAGE are omitted or specified as wildcard *. This option can be used multiple times.
- --uac-admin
Using this option creates a Manifest that will request elevation upon application start.
- --uac-uiaccess
Using this option allows an elevated application to work with Remote Desktop.
Windows Side-By-Side Assembly Searching Options (Advanced)¶
- --win-private-assemblies
Any Shared Assemblies bundled into the application will be changed into Private Assemblies. This means the exact versions of these assemblies will always be used, and any newer versions installed on user machines at the system level will be ignored.
- --win-no-prefer-redirects
While searching for Shared or Private Assemblies to bundle into the application, PyInstaller will prefer not to follow policies that redirect to newer versions, and will try to bundle the exact versions of the assembly.
Mac Os Specific Options¶
- --osx-bundle-identifier BUNDLE_IDENTIFIER
Mac OS .app bundle identifier is used as the default unique program name for code signing purposes. The usual form is a hierarchical name in reverse DNS notation. For example: com.mycompany.department.appname (default: first script’s basename)
- --target-architecture ARCH, --target-arch ARCH
Target architecture (macOS only; valid values: x86_64, arm64, universal2). Enables switching between universal2 and single-arch version of frozen application (provided python installation supports the target architecture). If not target architecture is not specified, the current running architecture is targeted.
- --codesign-identity IDENTITY
Code signing identity (macOS only). Use the provided identity to sign collected binaries and generated executable. If signing identity is not provided, ad- hoc signing is performed instead.
- --osx-entitlements-file FILENAME
Entitlements file to use when code-signing the collected binaries (macOS only).
Rarely Used Special Options¶
- --runtime-tmpdir PATH
Where to extract libraries and support files in onefile-mode. If this option is given, the bootloader will ignore any temp-folder location defined by the run-time OS. The
_MEIxxxxxx
-folder will be created here. Please use this option only if you know what you are doing.- --bootloader-ignore-signals
Tell the bootloader to ignore signals rather than forwarding them to the child process. Useful in situations where for example a supervisor process signals both the bootloader and the child (e.g., via a process group) to avoid signalling the child twice.
ENVIRONMENT VARIABLES¶
- PYINSTALLER_CONFIG_DIR
This changes the directory where PyInstaller caches some files. The default location for this is operating system dependent, but is typically a subdirectory of the home directory.
SEE ALSO¶
pyinstaller
(1),
The PyInstaller Manual https://pyinstaller.readthedocs.io/,
Project Homepage http://www.pyinstaller.org
Development Guide¶
Quickstart¶
Our git repository is at https://github.com/pyinstaller/pyinstaller:
git clone https://github.com/pyinstaller/pyinstaller
Development is done on the develop branch. Pull-request shall be filed against this branch.
Releases will reside on the master branch.
Install required testing tools:
pip install -r tests/requirements-tools.txt
Commit as often as you’d like, but squash or otherwise rewrite your commits into logical patches before asking for code review.
git rebase -i
is your friend. Read the »» Detailed Commit Guideline for more information.Reformatting code without functional changes will generally not be accepted (for rational see #2727).
Write meaningful commit messages.
The first line shall be a short sentence that can stand alone as a short description of the change, written in the present tense, and prefixed with the subsystem-name.
The body of the commit message should explain or justify the change. Read the »» Detailed Commit Message Rules for more information.
Provide tests that cover your changes and try to run the tests locally first.
Submit pull-requests against the
develop
branch. Mind adding a changelog entry so our users can learn about your change!For new files mind adding the copyright header, see
PyInstaller/__init__.py
(also mind updating to the current year).In response to feedback, squash the new “fix up” commits into the respective commit that is being fixed with an interactive rebase (
git rebase -i
). Push the new, rewritten branch with agit push --force
. (Scary! But github doesn’t play nicely with a safer method.)
New to GitHub or Git?¶
Our development workflow is build around Git and GitHub. Please take your time to become familiar with these. If you are new to GitHub, GitHub has instructions for getting you started. If you are new to Git there are a tutorial and an excellent book available online.
Further Reading
Coding conventions¶
The PyInstaller project follows the PEP 8 Style Guide for Python Code for new code. It uses yapf to do the bulk of the formatting (mostly putting spaces in the correct places) automatically and flake8 to validate PEP 8 rules which yapf doesn’t cover.
Before submitting changes to PyInstaller, please check your code with both tools.
To install them run:
pip install flake8 yapf==0.31.0 toml
Reformat your code automatically with yapf:
yapf -rip .
Then manually adjust your code based on any suggestions given by flake8:
git diff -U0 last-commit-id-which-you-did-not-write -- | flake8 --diff -
Please abstain from reformatting existing code, even it it doesn’t follow PEP 8. We will not accept reformatting changes since they make it harder to review the changes and to follow changes in the long run. For a complete rationale please see #2727.
Running the Test Suite¶
To run the test-suite, please proceed as follows.
If you don’t have a git clone of PyInstaller, first fetch the current development head, either using pip, …:
pip download --no-deps https://github.com/pyinstaller/pyinstaller/archive/develop.zip unzip develop.zip cd pyinstaller-develop/
… or using git:
git clone https://github.com/pyinstaller/pyinstaller.git cd pyinstaller
Then setup a fresh virtualenv for running the test suite in and install all required tools:
pip install --user virtualenv virtualenv /tmp/venv . /tmp/venv/bin/activate pip install -r tests/requirements-tools.txt
To run a single test use e.g.:
pytest tests/unit -k test_collect_submod_all_included
Run the test-suite:
pytest tests/unit tests/functional
This only runs the tests for the core functionality and some packages from the Python standard library.
To get better coverage, including many of the available hooks, you need to download the Python packages to be tested. For this please run:
pip install -U -r tests/requirements-libraries.txt pytest tests/unit tests/functional
To learn how we run the test-suite in the continuous integration tests please
have a look at .travis.yml
(for GNU/Linux and OS X) and appveyor.yml
(for Windows).
Guidelines for Commits¶
Please help keeping code and changes comprehensible for years. Provide a readable commit-history following this guideline.
A commit
stands alone as a single, complete, logical change,
has a descriptive commit message (see below),
has no extraneous modifications (whitespace changes, fixing a typo in an unrelated file, etc.),
follows established coding conventions (PEP 8) closely.
Avoid committing several unrelated changes in one go. It makes merging difficult, and also makes it harder to determine which change is the culprit if a bug crops up.
If you did several unrelated changes before committing, git gui
makes
committing selected parts and even selected lines easy. Try the context menu
within the windows diff area.
This results in a more readable history, which makes it easier to understand why a change was made. In case of an issue, it’s easier to git bisect to find breaking changes any revert those breaking changes.
In Detail¶
A commit should be one (and just one) logical unit. It should be something that someone might want to patch or revert in its entirety, and never piece-wise. If it could be useful in pieces, make separate commits.
Make small patches (i.e. work in consistent increments).
Reformatting code without functional changes will generally not be accepted (for rationale see #2727). If such changes are required, separate it into a commit of its own and document as such.
This means that when looking at patches later, we don’t have to wade through loads of non-functional changes to get to the relevant parts of the patch.
Especially don’t mix different types of change, and put a standard prefix for each type of change to identify it in your commit message.
Abstain refactorings! If any, restrict refactorings (that should not change functionality) to their own commit (and document).
Restrict functionality changes (bug fix or new feature) to their own changelists (and document).
If your commit-series includes any “fix up” commits (“Fix typo.”, “Fix test.”, “Remove commented code.”) please use
git rebase -i …
to clean them up prior to submitting a pull-request.Use
git rebase -i
to sort, squash, and fixup commits prior to submitting the pull-request. Make it a readable history, easy to understand what you’ve done.
Please Write Good Commit Messages¶
Please help keeping code and changes comprehensible for years. Write good commit messages following this guideline.
Commit messages should provide enough information to enable a third party to decide if the change is relevant to them and if they need to read the change itself.
PyInstaller is maintained since 2005 and we often need to comprehend years later why a certain change has been implemented as it is. What seemed to be obvious when the change was applied may be just obscure years later. The original contributor may be out of reach, while another developer needs to comprehend the reasons, side-effects and decisions the original author considered.
We learned that commit messages are important to comprehend changes and thus we are a bit picky about them.
We may ask you to reword your commit messages. In this case, use git
rebase -i …
and git push -f …
to update your pull-request. See
Updating a Pull-Request for details.
Content of the commit message¶
Write meaningful commit messages.
The first line shall be a short sentence that can stand alone as a short description of the change, written in the present tense, and prefixed with the subsystem-name. See below for details.
The body of the commit message should explain or justify the change, see below for details.
The first Line¶
The first line of the commit message shall
be a short sentence (≤ 72 characters maximum, but shoot for ≤ 50),
use the present tense (“Add awesome feature.”) 1,
be prefixed with an identifier for the subsystem this commit is related to (“tests: Fix the frob.” or “building: Make all nodes turn faster.”),
always end with a period.
Ending punctuation other than a period should be used to indicate that the summary line is incomplete and continues after the separator; “…” is conventional.
- 1
Consider these messages as the instructions for what applying the commit will do. Further this convention matches up with commit messages generated by commands like git merge and git revert.
The Commit-Message Body¶
The body of a commit log should:
explain or justify the change,
If you find yourself describing implementation details, this most probably should go into a source code comment.
Please include motivation for the change, and contrasts its implementation with previous behavior.
For more complicate or serious changes please document relevant decisions, contrast them with other possibilities for chosen, side-effect you experienced, or other thinks to keep in mind when touching this peace of code again. (Although the later might better go into a source code comment.)
for a bug fix, provide a ticket number or link to the ticket,
explain what changes were made at a high level (The GNU ChangeLog standard is worth a read),
be word-wrapped to 72 characters per line, don’t go over 80; and
separated by a blank line from the first line.
Bullet points and numbered lists are okay, too:
* Typically a hyphen or asterisk is used for the bullet, preceded by a single space, with blank lines in between, but conventions vary here. * Use a hanging indent.
Do not start your commit message with a hash-mark (
#
) as git some git commands may dismiss these message. (See this discussion. for details.)
Standard prefixes¶
Please state the “subsystem” this commit is related to as a prefix in the
first line. Do learn which prefixes others used for the files you changed you
can use git log --oneline path/to/file/or/dir
.
Examples for “subsystems” are:
Hooks
for hook-related changesBootloader
,Bootloader build
for the bootloader or it’s build systemdepend
for the dependency detection parts (PyInstaller/depend
)building
for the building part (PyInstaller/building
)compat
for code related to compatibility of different Python versions (primaryPyInstaller/compat.py
)loader
utils
,utils/hooks
Tests
,Test/CI
: For changes to the test suite (incl. requirements), resp. the CI.modulegraph
: changes related toPyInstaller/lib/modulegraph
Doc
,Doc build
for the documentation content resp. it’s build system. You may want to specify the chapter or section too.
Please set the correct Author¶
Please make sure you have setup git to use the correct name and email for your commits. Use the same name and email on all machines you may push from. Example:
# Set name and email
git config --global user.name "Firstname Lastname"
git config --global user.email "your_email@youremail.com"
This will set this name and email-address to be used for all git-repos you are
working on on this system. To set it for just the PyInstaller repo, remove the
--global
flag.
Alternatively you may use git gui
to set these values.Further Reading¶
Further hints and tutorials about writing good commit messages can also be found at:
http://365git.tumblr.com/post/3308646748/writing-git-commit-messages
http://wincent.com/blog/commit-messages: The Good, the Bad and the Ugly.
http://lbrandy.com/blog/2009/03/writing-better-commit-messages/
http://blog.looplabel.net/2008/07/28/best-practices-for-version-control/
http://subversion.apache.org/docs/community-guide/conventions.html (Targeted a bit too much to subversion usage, which does not use such fine-grained commits as we ask you strongly to use.)
Credits¶
This page was composed from material found at
Improving and Building the Documentation¶
PyInstaller’s documentation is created using Sphinx. Sphinx uses reStructuredText as its markup language, and many of its strengths come from the power and straightforwardness of reStructuredText and its parsing and translating suite, Docutils.
The documentation is maintained in the Git repository along with the code
and pushing to the develop
branch will create
a new version at https://pyinstaller.readthedocs.io/en/latest/.
For small changes (like typos) you may just fork PyInstaller on Github, edit the documentation online and create a pull-request.
For anything else we ask you to clone the repository and verify your changes like this:
pip install -r doc/requirements.txt
cd doc
make html
xdg-open _build/html/index.html
Please watch out for any warnings and errors while building the documentation. In your browser check if the markup is valid prior to pushing your changes and creating the pull-request. Please also run:
make clean
...
make html
to verify once again everything is fine. Thank you!
We may ask you to rework your changes or reword your commit messages. In this
case, use git rebase -i …
and git push -f …
to update your
pull-request. See Updating a Pull-Request for details.
PyInstaller extensions¶
For the PyInstaller documentation there are roles available * in additon to the ones from Sphinx and docutils.
- :commit:¶
Refer to a commit, creating a web-link to the online git repository. The commit-id will be shortened to 8 digits for readability. Example:
:commit:`a1b2c3d4e5f6a7b8c9`
will become a1b2c3d4.
- *
Defined in
doc/_extensions/pyi_sphinx_roles.py
reStructuredText Cheat-sheet¶
Combining markup and links:
The easies way to install PyInstaller is using |pip|_:: .. |pip| replace:: :command:`pip` .. _pip: https://pip.pypa.io/
Creating Pull-Requests¶
Example¶
Create an account on https://github.com
Create a fork of project pyinstaller/pyinstaller on github.
Set up your git client by following this documentation on github.
Clone your fork to your local machine.:
git clone git@github.com:YOUR_GITHUB_USERNAME/pyinstaller.git cd pyinstaller
Develop your changes (aka “hack”)
Create a branch to work on (optional):
git checkout -b my-patch
If you are going to implement a hook, start with creating a minimalistic build-test (see below). You will need to test your hook anyway, so why not use a build-test from the start?
Incorporate your changes into PyInstaller.
Test your changes by running all build tests to ensure nothing else is broken. Please test on as many platform as you can.
You may reference relevant issues in commit messages (like #1259) to make GitHub link issues and commits together, and with phrase like “fixes #1259” you can even close relevant issues automatically.
Synchronize your fork with the PyInstaller upstream repository. There are two ways for this:
Rebase you changes on the current development head (preferred, as it results in a straighter history and conflicts are easier to solve):
git remote add upstream https://github.com/pyinstaller/pyinstaller.git git checkout my-patch git pull --rebase upstream develop git log --online --graph
Merge the current development head into your changes:
git remote add upstream https://github.com/pyinstaller/pyinstaller.git git fetch upstream develop git checkout my-patch git merge upstream/develop git log --online --graph
For details see syncing a fork at github.
Push your changes up to your fork:
git push
Open the Pull Requests page at https://github.com/YOUR_GITHUB_USERNAME/pyinstaller/pulls and click “New pull request”. That’s it.
Updating a Pull-Request¶
We may ask you to update your pull-request to improve it’s quality or for
other reasons. In this case, use git rebase -i …
and git push -f …
as
explained below. 1 Please do not close the pull-request and open a new
one – this would kill the discussion thread.
This is the workflow without actually changing the base:
git checkout my-branch
# find the commit your branch forked from 'develop'
mb=$(git merge-base --fork-point develop)
# rebase interactively without actually changing the base
git rebase -i $mb
# … process rebase
git push -f my-fork my-branch
Or if you want to actually base your code on the current development head:
git checkout my-branch
# rebase interactively on 'develop'
git rebase -i develop
# … process rebase
git push -f my-fork my-branch
- 1
There are other ways to update a pull-request, e.g. by “amending” a commit. But for casual (and not-so-casual :-) users
rebase -i
might be the easiest way.
Changelog Entries¶
If your change is noteworthy, there needs to be a changelog entry so our users can learn about it!
To avoid merge conflicts, we use the towncrier package to manage our
changelog. towncrier
uses independent files for each pull request –
called news fragments – instead of one monolithic changelog file. On
release, those news fragments are compiled into our doc/CHANGELOG.rst
.
You don’t need to install towncrier
yourself, you just have to abide by a
few simple rules:
For each pull request, add a new file into news/ with a filename adhering to the
pr#.(feature|bugfix|breaking).rst
schema: For example,news/42.feature.rst
for a new feature that is proposed in pull request #42.Our categories are:
feature
,bugfix
,breaking
(breaking changes),hooks
(all hook-related changes),bootloader
,moduleloader
,doc
,process
(project infrastructure, development process, etc.),core
,build
(the bootloader build process), andtests
.As with other docs, please use semantic newlines within news fragments.
Prefer present tense or constructions with “now” or “new”. For example:
Add hook for my-fancy-library.
Fix crash when trying to add resources to Windows executable using
--resource
option.
If the change is relavant only fo a specific platform, use a prefix, like here:
(GNU/Linux) When building with
--debug
turn of FORTIFY_SOURCE to ease debugging.
Wrap symbols like modules, functions, or classes into double backticks so they are rendered in a monospace font. If you mention functions or other callables, add parentheses at the end of their names:
is_module()
. This makes the changelog a lot more readable.If you want to reference multiple issues, copy the news fragment to another filename.
towncrier
will merge all news fragments with identical contents into one entry with multiple links to the respective pull requests. You may also reference to an existing newsfragment by copying that one.If your pull-request includes several distinct topics, you may want to add several news fragment files. For example
4242.feature.rst
for the new feature,4242.bootloader
for the accompanying change to the bootloader.
Remember that a news entry is meant for end users and should only contain details relevant to an end user.
pyenv and PyInstaller¶
Note
This section is a still a draft. Please help extending it.
clone pyenv repository:
git clone https://github.com/yyuu/pyenv.git ~/.pyenv
clone virtualenv plugin:
git clone https://github.com/yyuu/pyenv-virtualenv.git \ ~/.pyenv/plugins/pyenv-virtualenv
add to .bashrc or .zshrc:
# Add 'pyenv' to PATH. export PYENV_ROOT="$HOME/.pyenv" export PATH="$PYENV_ROOT/bin:$PATH" # Enable shims and autocompletion for pyenv. eval "$(pyenv init -)" # Load pyenv-virtualenv automatically by adding # # the following to ~/.zshrc: # eval "$(pyenv virtualenv-init -)"
Install python version with shared libpython (necessary for PyInstaller to work):
env PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv install 3.5.0
setup virtualenv
pyenv virtualenv 3.5.0 venvname
activate virtualenv
pyenv activate venvname
deactivate virtualenv
pyenv deactivate
PyInstaller’s Branch Model¶
- develop branch
We consider origin/develop to be the main branch where the source code of HEAD always reflects a state with the latest delivered development changes for the next release. Some would call this the “integration branch”.
- master branch
We consider origin/master to be the main branch where the source code of HEAD always reflects a production-ready state. Each commit to master is considered a new release and will be tagged.
The PyInstaller project doesn’t use long living branches (beside master and develop) as we don’t support bugfixes for several major releases in parallel.
Occasionally you might find these branches in the repository: 1
- release/ branches
These branches are for preparing the next release. This is for example: updating the version numbers, completing the change-log, recompiling the bootloader, rebuilding the manuals. See ref:release-workflow for details about the release process and what steps have to be performed.
- hotfix/ branches
These branches are also meant to prepare for a new production release, albeit unplanned. This is what is commonly known as a “hotfix”.
- feature/ branches
Feature branches (or sometimes called topic branches) are used to develop new features for the upcoming or a distant future release.
- 1
This branching-model is basically the same as Vincent Driessen described in this blog. But currently we are not following it strictly.