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 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.
Options
- -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)
- —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, DEPRECATION,
ERROR, FATAL (default: INFO). Also settable via and
overrides the PYI_LOG_LEVEL environment variable.
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 to assign to the bundled app and spec file
(default: first script’s basename)
- —contents-directory CONTENTS_DIRECTORY
-
For onedir builds only, specify the name of the directory in which all
supporting files (i.e. everything except the executable itself) will be
placed in. Use “.” to re-enable old onedir layout without contents
directory.
What To Bundle, Where To Search
- —add-data SOURCE:DEST
-
Additional data files or directories containing data files to be added to
the application. The argument value should be in form of “source:dest_dir”,
where source is the path to file (or directory) to be collected, dest_dir
is the destination directory relative to the top-level application
directory, and both paths are separated by a colon (:). To put a file in
the top-level application directory, use . as a dest_dir. This option can
be used multiple times.
- —add-binary SOURCE:DEST
-
Additional binary files to be added to the executable. See the
--add-data
option for the format. This option can be used multiple
times.
- -p, —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, —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, —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.
- —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, —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.
- —optimize LEVEL
-
Bytecode optimization level used for collected python
modules and scripts. For details, see the section
“Bytecode Optimization Level” in PyInstaller manual.
- —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”, “W <warning
control>”, “X <xoption>”, and “hash_seed=<value>”. For details, see the
section “Specifying Python Interpreter Options” in PyInstaller manual.
- -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 Macos 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 macOS: do not provide a console window for standard i/o. On
macOS this also triggers building a macOS .app bundle. On Windows this
option is automatically set if the first script is a ‘.pyw’ file. This
option is ignored on *NIX systems.
- —hide-console {hide-late,hide-early,minimize-late,minimize-early}
-
Windows only: in console-enabled executable, have bootloader automatically
hide or minimize the console window if the program owns the console window
(i.e., was not launched from an existing console window).
- -i, —icon <FILE.ico or FILE.exe,ID or FILE.icns or Image 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
macOS. If an image file is entered that isn’t in the platform format (ico
on Windows, icns on Mac), PyInstaller tries to use Pillow to translate the
icon into the correct format (if Pillow is installed). Use “NONE” to not
apply any icon, thereby making the OS show some default (default: apply
PyInstaller’s icon). This option can be used multiple times.
- —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.
- —manifest <FILE or XML>
-
Add manifest FILE or XML to the exe.
- -m <FILE or XML>
-
Deprecated shorthand for –manifest.
- -r, —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.
Macos Specific Options
- —argv-emulation
-
Enable argv emulation for macOS app bundles. If
enabled, the initial open document/URL event is
processed by the bootloader and the passed file paths
or URLs are appended to sys.argv.
- —osx-bundle-identifier BUNDLE_IDENTIFIER
-
macOS .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, —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. Note that on
POSIX systems, PyInstaller’s bootloader does NOT perform shell-style
environment variable expansion on the given path string. Therefore, using
environment variables (e.g.,~
or$HOME
) in path will NOT work.
- —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 for compressing executable files and libraries.
It 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 file formats.
When UPX is available, PyInstaller uses it to individually compress
each collected binary file (executable, shared library, or python
extension) in order to reduce the overall size of the frozen application
(the one-dir bundle directory, or the one-file executable). The frozen
application’s executable itself is not UPX-compressed (regardless of one-dir
or one-file mode), as most of its size comprises the embedded archive that
already contains individually compressed files.
PyInstaller looks for the UPX in the standard executable path(s) (defined
by PATH
environment variable), or in the path specified via the
--upx-dir
command-line option. If found, it is used automatically.
The use of UPX can be completely disabled using the --noupx
command-line option.
Note
UPX is currently used only on Windows. On other operating systems,
the collected binaries are not processed even if UPX is found. The
shared libraries (e.g., the Python shared library) built on modern
linux distributions seem to break when processed with UPX, resulting
in defunct application bundles. On macOS, UPX currently fails to
process .dylib shared libraries; furthermore the UPX-compressed files
fail the validation check of the codesign
utility, and therefore
cannot be code-signed (which is a requirement on the Apple M1 platform).
Excluding problematic files from UPX processing
Using UPX may end up corrupting a collected shared library. Known examples
of such corruption are Windows DLLs with Control Flow Guard (CFG) enabled, as well as Qt5 and Qt6
plugins. In such cases,
individual files may be need to be excluded from UPX processing, using
the --upx-exclude
option (or using the upx_exclude
argument
in the .spec file).
Changed in version 4.2: PyInstaller detects CFG-enabled DLLs and automatically excludes
them from UPX processing.
Changed in version 4.3: PyInstaller automatically excludes Qt5 and Qt6 plugins from
UPX processing.
Although PyInstaller attempts to automatically detect and exclude some of
the problematic files from UPX processing, there are cases where the
UPX excludes need to be specified manually. For example, 32-bit Windows
binaries from the PySide2
package (Qt5 DLLs and python extension modules)
have been reported
to be corrupted by UPX.
Changed in version 5.0: Unlike earlier releases that compared the provided UPX-exclude names
against basenames of the collect binary files (and, due to incomplete
case normalization, required provided exclude names to be lowercase
on Windows), the UPX-exclude pattern matching now uses OS-default
case sensitivity and supports the wildcard (*
) operator. It also
supports specifying (full or partial) parent path of the file.
The provided UPX exclude patterns are matched against source (origin)
paths of the collected binary files, and the matching is performed from
right to left.
For example, to exclude Qt5 DLLs from the PySide2 package, use
--upx-exclude "Qt*.dll"
, and to exclude the python extensions
from the PySide2 package, use --upx-exclude "PySide2\*.pyd"
.
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.
Note
Splash images with transparent regions are not supported on Linux due to
Tcl/Tk platform limitations. The -transparentcolor
and -transparent
wm attributes
used by PyInstaller are not available to Linux.
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).
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 macOS, 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 macOS, 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 macOS, 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 macOS App Bundles
Under macOS, 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 a macOS app bundle named myscript.app
.
Note
Generating app bundles with onefile executables (i.e., using the
combination of --onefile
and --windowed
options),
while possible, is not recommended. Such app bundles are inefficient,
because they require unpacking on each run (and the unpacked content
might be scanned by the OS each time). Furthermore, onefile executables
will not work when signed/notarized with sandbox enabled (which
is a requirement for distribution of apps through Mac App Store).
As you are likely aware, an app bundle is a special type of folder.
The one built by PyInstaller always contains a folder named
Contents
, which contains:
A file named
Info.plist
that describes the app.A folder named
MacOS
that contains the program executable.A folder named
Frameworks
that contains the collected binaries
(shared libraries, python extensions) and nested .framework bundles.
It also contains symbolic links to data files and directories from
theResources
directory.A folder named
Resources
that contains the icon file and all
collected data files. It also contains symbolic links to binaries
and directories from theResources
directory.
Note
The contents of the Frameworks
and Resources
directories
are cross-linked between the two directories in an effort to
maintain an illusion of a single content directory (which is required
by some packages), while also trying to satisfy the Apple’s file
placement requirements for codesigning.
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 macOS 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.
Note that PyInstaller does bundle other shared libraries that are discovered
via dependency analysis, such as libstdc++.so.6, libfontconfig.so.1,
libfreetype.so.6. These libraries may be required on systems where older
(and thus incompatible) versions of these libraries are available. On the
other hand, the bundled libraries may cause issues when trying to load a
system-provided shared library that is linked against a newer version of the
system-provided library.
For example, system-installed mesa DRI drivers (e.g., radeonsi_dri.so)
depend on the system-provided version of libstdc++.so.6. If the frozen
application bundles an older version of libstdc++.so.6 (as collected from
the build system), this will likely cause missing symbol errors and prevent
the DRI drivers from loading. In this case, the bundled libstdc++.so.6
should be removed. However, this may not work on a different distribution
that provides libstdc++.so.6 older than the one from the build system; in
that case, the bundled version should be kept, because the system-provided
version may lack the symbols required by other collected binaries that depend
on libstdc++.so.6.
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.
macOS
Making macOS apps Forward-Compatible
On macOS, system components from one version of the OS are usually compatible
with later versions, but they may not work with earlier versions. While
PyInstaller does not collect system components of the OS, the collected
3rd party binaries (e.g., python extension modules) are built against
specific version of the OS libraries, and may or may not support older
OS versions.
As such, the only way to ensure that your frozen application supports
an older version of the OS is to freeze it on the oldest version of the
OS that you wish to support. This applies especially when building with
Homebrew python, as its binaries usually explicitly target the
running OS.
For example, to ensure compatibility with “Mojave” (10.14) and later versions,
you should set up a full environment (i.e., install python, PyInstaller,
your application’s code, and all its dependencies) in a copy of macOS 10.14,
using a virtual machine if necessary. Then use PyInstaller to freeze
your application in that environment; the generated frozen application
should be compatible with that and later versions of macOS.
Building 32-bit Apps in macOS
Note
This section is largely obsolete, as support for 32-bit application
was removed in macOS 10.15 Catalina (for 64-bit multi-arch support
on modern versions of macOS, see here).
However, PyInstaller still supports building 32-bit bootloader,
and 32-bit/64-bit Python installers are still available from
python.org for (some) versions of Python 3.7 which PyInstaller dropped
support for in v6.0.
Older versions of macOS 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.
To verify that the installed python version supports execution in either
64- or 32-bit mode, use the file
command on 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.7.6 (v3.7.6:43364a7ae0, Dec 18 2019, 14:12:53) [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.7.6 (v3.7.6:43364a7ae0, Dec 18 2019, 14:12:53) [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
Note
PyInstaller does not provide pre-built 32-bit bootloaders for
macOS anymore. In order to use PyInstaller with 32-bit python,
you need to build the bootloader
yourself, using an XCode
version that still supports compiling 32-bit. Depending on the
compiler/toolchain, you may also need to explicitly pass
--target-arch=32bit
to the waf
command.
Getting the Opened Document Names
When user double-clicks a document of a type that is registered with
your application, or when a user drags a document and drops it
on your application’s icon, macOS launches your application
and provides the name(s) of the opened document(s) in the
form of an OpenDocument AppleEvent.
These events are typically handled via installed event handlers in your
application (e.g., using Carbon
API via ctypes
, or using
facilities provided by UI toolkits, such as tkinter
or PyQt5
).
Alternatively, PyInstaller also supports conversion of open
document/URL events into arguments that are appended to sys.argv
.
This applies only to events received during application launch, i.e.,
before your frozen code is started. To handle events that are dispatched
while your application is already running, you need to set up corresponding
event handlers.
For details, see this section.
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>
Cygwin
Cygwin-based Frozen Applications and cygwin1.dll
Under Cygwin, the PyInstaller’s bootloader executable (and therefore the
frozen application’s executable) ends up being dynamically linked against
the cygwin1.dll
. As noted under Q 6.14 of the Cygwin’s FAQ,
the Cygwin library cannot be statically linked into an executable in
order to obtain an independent, self-contained executable.
This means that at run-time, the cygwin1.dll
needs to be available
to the frozen application’s executable for it to be able to launch.
Depending on the deployment scenario, this means that it needs to be
either available in the environment (i.e., the environment’s search path)
or a copy of the DLL needs to be available next to the executable.
On the other hand, Cygwin does not permit more than one copy of
cygwin1.dll
; or rather, it requires multiple copies of the DLL
to be strictly separated, as each instance constitutes its own Cygwin
installation/environment (see Q 4.20 of the Cygwin FAQ).
Trying to run an executable with an adjacent copy of the DLL from an
existing Cygwin environment will likely result in the application crashing.
In practice, this means that if you want to create a frozen application
that will run in an existing Cygwin environment, the application
should not bundle a copy of cygwin1.dll
. On the other hand, if you
want to create a frozen application that will run outside of a Cygwin
environment (i.e., a “stand-alone” application that runs directly under
Windows), the application will require a copy of cygwin1.dll
– and
that copy needs to be placed next to the program’s executable, regardless
of whether onedir
or onefile
build mode is used.
As PyInstaller cannot guess the deployment mode that you are pursuing,
it makes no attempt to collect cygwin1.dll
. So if you want your
application to run outside of an externally-provided Cygwin environment,
you need to place a copy of cygwin1.dll
next to the program’s
executable and distribute them together.
Note
If you plan to create a “stand-alone” Cygwin-based frozen application
(i.e., distribute cygwin1.dll
along with the executable), you will
likely want to build the bootloader with statically linked zlib
library, in order to avoid a run-time dependency on cygz.dll
.
You can do so by passing --static-zlib
option to waf
when
manually building the bootloader before installing PyInstaller
from source, or by adding the option to PYINSTALLER_BOOTLOADER_WAF_ARGS
environment variable if installing directly via pip install
.
For details, see 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 from our GitHub repository,
-
cd
into the folder where you cloned or unpacked the source to, -
cd bootloader
, and -
make 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
(macOS and Windows only), and -
../PyInstaller/bootloader/OS_ARCH/runw_d
(macOS 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. Doing so would execute the command python ./waf configure all
upon installation. You can also pass additional arguments to the build process by setting the PYINSTALLER_BOOTLOADER_WAF_ARGS
environment variable.
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 for macOS
On macOS please install Xcode, Apple’s suite of tools for developing
software for macOS.
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.
The --no-universal2
flag leaves the target architecture unspecified letting
the resultant executable’s architecture be the C compiler’s default (which is
almost certainly the architecture of the build machine). Should you want to
build a thin executable of either architecture, use the --no-universal2
flag
and then optionally override the compiler, adding the -arch
flag, via the
CC
environment variable.
Build a thin, native executable:
python waf --no-universal2 all
Build a thin, x86_64
executable (regardless of the build machine’s
architecture):
CC='clang -arch x86_64' python waf --no-universal2 all
Build a thin, arm64
executable (regardless of the build machine’s
architecture):
CC='clang -arch arm64' python waf --no-universal2 all
By default, the build script targets macOS 10.13, which can be overridden by
exporting the MACOSX_DEPLOYMENT_TARGET environment variable.
Cross-Building for macOS
For cross-compiling for macOS you need the Clang/LLVM compiler, the
cctools (ld, lipo, …), and the macOS 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 macOS 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. [1]
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
usingvagrant destroy build-osxcross
.
Building the Bootloader
Again, simply use the Vagrantfile to automatically build the macOS bootloaders:
export TARGET=OSX # make the Vagrantfile build for macOS vagrant up linux64 && vagrant halt linux64
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 macOS bootloaders, unset TARGET again:
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 [2]
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.
-
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:
-
Microsoft Visual C++ Build-Tools 2015
-
Microsoft Build-Tools for Visual Studio 2017.
-
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:
-
MinGW-w64 required, uses gcc 4.4 and up.
-
TDM-GCC — MinGW (not used) and MinGW-w64 installers
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 [3] will automatically build the bootloader when running
vagrant up GUEST or
vagrant provision GUEST. They will build both 32- and 64-bit bootloaders.
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 macOS
(see Cross-Building for macOS). -
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 macOS SDK and cctools as
described in section Cross-Building for macOS.
C помощью Python можно автоматизировать многие задачи — достаточно написать скрипт и запустить его на терминале. Python — самый быстрый и простой язык сценариев. Если вы не хотите каждый день открывать терминал и запускать одну и ту же команду, можно создать исполняемый файл. Создать exe-файл в Python можно с помощью PyInstaller и других библиотек.
Создание exe-файла с помощью библиотеки PyInstaller
PyInstaller — популярный инструмент для преобразования скриптов Python в автономные исполняемые файлы (.exe) в Windows.
Установка PyInstaller
PyInstaller доступен в виде обычного пакета Python. Архивы с исходными текстами для выпущенных версий доступны в PyPI, но инструмент проще установить с помощью pip:
C:\> pip install pyinstaller
Это поможет обновить PyInstaller до последней версии:
C:\> pip install —upgrade pyinstaller
Установка текущей версии разработки:
C:\> pip install https://github.com/pyinstaller/pyinstaller/tarball/
Алгоритм действия
В качестве примера возьмем один файл на Python, чтобы подробно объяснить этапы упаковки. Рассмотрим Python 3.11.0 после установки aspose.cells.
1.Создайте файл с именем example.py:
import os
from jpype import *
__cells_jar_dir__ = os.path.dirname(__file__)
addClassPath(os.path.join(__cells_jar_dir__, "aspose-cells-23.1.jar"))
addClassPath(os.path.join(__cells_jar_dir__, "bcprov-jdk15on-160.jar"))
addClassPath(os.path.join(__cells_jar_dir__, "bcpkix-jdk15on-1.60.jar"))
addClassPath(os.path.join(__cells_jar_dir__, "JavaClassBridge.jar"))
import jpype
import asposecells
jpype.startJVM()
from asposecells.api import Workbook, FileFormatType, CellsHelper
print(CellsHelper.getVersion())
workbook = Workbook(FileFormatType.XLSX)
workbook.getWorksheets().get(0).getCells().get("A1").putValue("Hello World")
workbook.save("output.xlsx")
jpype.shutdownJVM()
py
2.Создайте папку c:\app и копию example.py c:\app.
3. Откройте командную строку и выполните команду example.py pyinstaller
C:\app> pyinstaller example.py
4. Скопируйте файлы jar(aspose-cells-xxx.jar, bcprov-jdk15on-160.jar, bcpkix-jdk15on-1.60.jar, JavaClassBridge.jar. Они находятся в папке C:\Python311\Lib\site-packages\asposecells\lib) в c:\app.
5. Отредактируйте файл с суффиксом spec, чтобы добавить раздел данных, подобный example.spec.
6. Запустите pyinstaller example.spec в окне командной строки.
C:\app> pyinstaller example.spec
7. Переключите каталог на C:\app\dist\example, и вы найдете файл example.exe.
Создание exe-файла с помощью библиотеки auto-py-to-exe
С помощью auto-py-to-exe, проекта Брента Воллебрегта можно создавать собственные исполняемые приложения на Python. Под графическим интерфейсом находится PyInstaller, приложение на базе терминала для создания исполняемых файлов на Python для Windows, Mac и Linux.
Установка auto-py-to-exe
- Откройте командную строку, выполнив поиск CMD.
- Используйте pip-менеджер пакетов Python для установки auto-py-to-exe:
pip install auto-py-to-exe
Алгоритм действия
- Откройте командную строку, выполнив поиск CMD.
- Запустите auto-py-to-exe из командной строки.
- Нажмите на кнопку Browse и перейдите к нашему примеру файла на Python.
- Настройте приложение на использование одного файла. Это позволит объединить приложение и поддерживающие его библиотеки Python в один исполняемый файл.
- Настройте приложение на консольное управление. Так можно увидеть все ошибки, выводимые в командную строку. Как только мы будем уверены, что приложение работает правильно, можно настроить его на оконное управление.
- Нажмите на раскрывающийся список параметров и выберите значок для вашего приложения. Это необязательный шаг, но он повышает качество приложения.
- Нажмите «Дополнительно», в поле «Имя» введите название вашего приложения. Например, «Программа запуска приложений».
- Прокрутите страницу вниз и нажмите «Преобразовать. PY в .EXE», чтобы начать процесс. Это займет пару минут.
- Нажмите на кнопку Open Output Folder, чтобы открыть папку, содержащую приложение.
- Дважды щелкните по значку, чтобы запустить приложение.
Создание exe-файла с помощью библиотеки cx_Freeze
Преобразовать скрипт Python в автономный исполняемый файл (.exe) можно и с помощью «cx_Freeze».
Установка cx_Freeze
Установить его легко с помощью pip:
Алгоритм действия
Создайте установочный скрипт (например, «setup.py») в том же каталоге, что и ваш скрипт на Python. Этот скрипт предоставит конфигурацию для «cx_Freeze». Простой пример проекта:
from cx_Freeze import setup, Executable
setup(
name="YourAppName",
version="1.0",
description="Your application description",
executables=[Executable("your_script.py")],
)
py
Замените «YourAppName» и «Your application description» на название и описание вашего приложения, а «your_script.py» — на название вашего скрипта на Python.
Откройте терминал, перейдите в каталог, содержащий ваш скрипт на Python и файл «setup.py»:
python setup.py build
Это создаст каталог «build», содержащий исполняемый файл.
После выполнения команды «build» вы можете найти исполняемый файл в каталоге `build`. Он будет находиться в подкаталоге с названием вашей операционной системы (например, «build\exe.win-amd64-3.8» для 64-разрядного исполняемого файла Windows).
Теперь у вас должен быть отдельный исполняемый файл, который вы можете распространять и запускать на компьютере без установленного Python. Помните, что если у вашего скрипта есть внешние зависимости, то может потребоваться включить их в сценарий «setup.py».
Создание exe-файла с помощью библиотеки py2exe
Преобразование интерпретируемого языкового кода в исполняемый файл еще называют замораживанием. Для этого можно использовать модуль py2exe.
Установка py2exe
Чтобы использовать модуль py2exe, нужно его установить. Сделаем это с помощью pip:
Алгоритм действия
Напишем программу, которая будет выводить текст на консоль:
import math
print("Hannibal ante Portas")
print(factorial(4))
py
Запустим следующие команды в командной строке Windows, чтобы создать каталог. Переместим код, который мы уже написали в указанный каталог и выполним его:
$ mkdir exampDir
$ move example.py exampDir
$ cd exampDir
$ py example.py
py
Всегда проверяйте скрипты, прежде чем превращать их в исполняемые файлы, чтобы убедиться, что если и есть ошибка, то она вызвана не исходным кодом.
Создайте другой файл с именем setup.py в той же папке. Здесь мы сохраним подробную информацию о конфигурации, о том, как мы хотим скомпилировать нашу программу. Пока мы просто добавим в него пару строк кода:
from distutils.core import setup # Need this to handle modules
import py2exe
import math # We have to import all modules used in our program
setup(console=['example.py']) # Calls setup function to indicate that we're dealing with a single console application
py
Теперь откройте командную строку от имени администратора и перейдите в каталог, чтобы запустить файл setup.py:
$ cd exampDir
$ python setup.py py2exe
running py2exe
*** searching for required modules ***
*** parsing results ***
…
PyInstaller Overview
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.
Documentation: | https://pyinstaller.org/ |
---|---|
Code: | https://github.com/pyinstaller/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.
PyInstaller is tested against Windows, macOS, 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 is not tested against them as part of the continuous integration tests.
Main Advantages
- Works out-of-the-box with any Python version 3.8-3.13.
- Fully multi-platform, and uses the OS support to load the dynamic libraries,
thus ensuring full compatibility. - Correctly bundles the major Python packages such as numpy, PyQt5,
PySide2, PyQt6, PySide6, wxPython, matplotlib and others out-of-the-box. - Compatible with many 3rd-party packages out-of-the-box. (All the required
tricks to make external packages work are already integrated.) - Works with code signing on macOS.
- Bundles MS Visual C++ DLLs on Windows.
Installation
PyInstaller is available on PyPI. You can install it through pip:
Requirements and Tested Platforms
-
- Python:
-
- 3.8-3.13. Note that Python 3.10.0 contains a bug making it unsupportable by
PyInstaller. PyInstaller will also not work with beta releases of Python
3.14.
- 3.8-3.13. Note that Python 3.10.0 contains a bug making it unsupportable by
-
- Windows (32bit/64bit/ARM64):
-
- PyInstaller should work on Windows 7 or newer, but we only officially support Windows 8+.
- Support for Python installed from the Windows store without using virtual
environments requires PyInstaller 4.4 or later.
-
- Linux:
-
- GNU libc based distributions on architectures
x86_64
,aarch64
,
i686
,ppc64le
,s390x
. - musl libc based distributions on architectures
x86_64
,aarch64
. - ldd: Console application to print the shared libraries required
by each program or shared library. This typically can be found in
the distribution-package glibc or libc-bin. - objdump: Console application to display information from
object files. This typically can be found in the
distribution-package binutils. - objcopy: Console application to copy and translate object files.
This typically can be found in the distribution-package binutils,
too. - Raspberry Pi users on
armv5
—armv7
should add piwheels as an extra
index url thenpip install pyinstaller
as usual.
- GNU libc based distributions on architectures
-
- macOS (
x86_64
orarm64
): -
- macOS 10.15 (Catalina) or newer.
- Supports building
universal2
applications provided that your installation
of Python and all your dependencies are also compileduniversal2
.
- macOS (
Usage
Basic usage is very simple, just run it against your main script:
pyinstaller /path/to/yourscript.py
For more details, see the manual.
Untested Platforms
The following platforms have been contributed and any feedback or
enhancements on these are welcome.
-
- FreeBSD
-
- ldd
-
- Solaris
-
- ldd
- objdump
-
- AIX
-
- AIX 6.1 or newer. PyInstaller will not work with statically
linked Python libraries. - ldd
- AIX 6.1 or newer. PyInstaller will not work with statically
- Linux on any other libc implementation/architecture combination not listed
above.
Before using any contributed platform, you need to build the PyInstaller
bootloader. This will happen automatically when you pip install pyinstaller
provided that you have an appropriate C compiler (typically
either gcc
or clang
) and zlib’s development headers already installed.
Support
- Official debugging guide: https://pyinstaller.org/en/v6.13.0/when-things-go-wrong.html
- Assorted user contributed help topics: https://github.com/pyinstaller/pyinstaller/wiki
- Web based Q&A forums: https://github.com/pyinstaller/pyinstaller/discussions
- Email based Q&A forums: https://groups.google.com/g/pyinstaller
Changes in this Release
You can find a detailed list of changes in this release
in the Changelog section of the manual.
Время на прочтение4 мин
Количество просмотров156K
Причиной написания статьи, явилось огромное количество постоянно возникающих у новичков вопросов такого содержания: «Как собрать проект c pyqt5», «Почему не работает», «Какой инструмент выбрать» и т.д. Сегодня научимся собирать проекты без мучений и танцев с бубном.
Как-то пришлось написать небольшое desktop-приложение. В качестве языка программирования для разработки был выбран python, поскольку для решения моей задачи он подходил идеально. В стандартную библиотеку Python уже входит библиотека tkinter, позволяющая создавать GUI. Но проблема tkinter в том, что данной библиотеке посвящено мало внимания, и найти в интернете курс, книгу или FAQ по ней довольно-таки сложно. Поэтому было решено использовать более мощную, современную и функциональную библиотеку Qt, которая имеет привязки к языку программирования python в виде библиотеки PyQT5. Более подробно про PyQT можете почитать здесь. В качестве примера я буду использовать код:
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QIcon
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(300, 300, 300, 220)
self.setWindowTitle('Icon')
self.setWindowIcon(QIcon('web.png'))
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
Если вы более-менее опытный разработчик, то понимаете, что без интерпретатора код на python не запустить. А хотелось бы дать возможность каждому пользователю использовать программу. Вот здесь к нам на помощь и приходят специальные библиотеки позволяющие собирать проекты в .exe, которые можно потом без проблем запустить, как обычное приложение.
Существует большое количество библиотек, позволяющих это сделать, среди которых самые популярные: cx_Freeze, py2exe, nuitka, PyInstaller и др. Про каждую написано довольно много. Но надо сказать, что многие из этих решений позволяют запускать код только на компьютере, с предустановленным интерпретатором и pyqt5. Не думаю, что пользователь будет заморачиваться и ставить себе дополнительные пакеты и программы. Надеюсь, вы понимаете, что запуск программы на dev-среде и у пользователя это не одно и тоже. Также нужно отметить, что у каждого решения были свои проблемы: один не запускался, другой собирал то, что не смог потом запустить, третий вообще отказывался что-либо делать.
После долгих танцев с бубном и активным гуглением, мне все же удалось собрать проект с помощью pyinstaller, в полностью работоспособное приложение.
Немного о Pyinstaller
Pyinstaller собирает python-приложение и все зависимости в один пакет. Пользователь может запускать приложение без установки интерпретатора python или каких-либо модулей. Pyinstaller поддерживает python 2.7 и python 3.3+ и такие библиотеки как: numpy, PyQt, Django, wxPython и другие.
Pyinstaller тестировался на Windows, Mac OS X и Linux. Как бы там ни было, это не кросс-платформенный компилятор: чтобы сделать приложение под Windows, делай это на Windows; Чтобы сделать приложение под Linux, делай это на Linux и т.д.
PyInstaller успешно используется с AIX, Solaris и FreeBSD, но тестирование не проводилось.
Подробнее о PyInstaller можно почитать здесь: документация.
К тому же после сборки приложение весило всего около 15 мб. Это к слову и является преимуществом pyinstaller, поскольку он не собирает все подряд, а только необходимое. Аналогичные же библиотеки выдавали результат за 200-300 мб.
Приступаем к сборке
Прежде чем приступить к сборке мы должны установить необходимые библиотеки, а именно pywin32 и собственно pyinstaller:
pip install pypiwin32
pip install pyinstaller
Чтобы убедится, что все нормально установилось, вводим команду:
pyinstaller --version
должна высветиться версия pyinstaller. Если все правильно установилось, идем дальше.
В папке с проектом запускаем cmd и набираем:
pyinstaller myscript.py
Собственно это и есть простейшая команда, которая соберет наш проект.
Синтаксис команды pyinstaller таков:
pyinstaller [options] script [script …] | specfile
Наиболее часто используемые опции:
—onefile — сборка в один файл, т.е. файлы .dll не пишутся.
—windowed -при запуске приложения, будет появляться консоль.
—noconsole — при запуске приложения, консоль появляться не будет.
—icon=app.ico — добавляем иконку в окно.
—paths — возможность вручную прописать путь к необходимым файлам, если pyinstaller
не может их найти(например: —paths D:\python35\Lib\site-packages\PyQt5\Qt\bin)
PyInstaller анализирует файл myscript.py и делает следующее:
- Пишет файл myscript.spec в той же папке, где находится скрипт.
- Создает папку build в той же папке, где находится скрипт.
- Записывает некоторые логи и рабочие файлы в папку build.
- Создает папку dist в той же папке, где находится скрипт.
- Пишет исполняемый файл в папку dist.
В итоге наша команда будет выглядеть так:
pyinstaller --onefile --icon=name.ico --noconsole myscript.py
После работы программы вы найдете две папки: dist и build. Собственно в папке dist и находится наше приложение. Впоследствии папку build можно спокойно удалить, она не влияет на работоспособность приложения.
Спасибо за внимание. Надеюсь статья была вам полезна.