Try   HackMD

Python .py to .exe using pyinstaller

There are a bunch of tutorials showing how to pack your .py code to an executable(such as .exe in windows). However, most of them just show one or two command packing the executable in the simplest way. In this note, I will also show you the basic, the simplest way to pack your executable and I will also show you how to deal with the annoying import errors.
I believe that PyPi page of pyinstaller helps alot.

Install pyinstaller

If you have pip installed:

pip install pyinstaller

If pip is not available in your enviroment, then you can download the archive and unzip it. Excute following with administration access:

python setup.py install

To verify installation:

pyinstaller --version

Ref: How to Install PyInstaller

Pack your executable

pyinstaller follows the pattern:

pyinstaller [options] script.py [script2.py …] | specfile

For a simplest case:

pyinstaller main.py

This command does:

  • Create ./build/, where logging and middle biniary files located.
  • Create ./dist/, where your executable and bundle apps located. Bulndle apps are imported packages.
  • Create main.spec
  • Generate a executabl according to main.spec
    If you want your executable to run without external files as dependencies, you can pack everythin into one file:
pyinstaller -F main.py

Here are some example with common options:

# Create a one-folder bundle containing an executable (default)
pyinstaller -D main.py

# Create a one-file bundled executable.
pyinstaller -F main.py

# Do not provide a console window for standard i/o. 
# On Mac OS X this also triggers building an OS X .app bundle. 
# On Windows this option will be set if the first script is a ‘.pyw’ file. 
# This option is ignored in *NIX systems.
pyinstaller --windowed main.py

# Open a console window for standard i/o (default).
# On Windows this option has no effect if the first script is a ‘.pyw’ file.
pyinstaller --console main.py

# Display an icon on the executable file, this option is only valid for windows and mac
# note that the icon file should be in ico format, you can google "ico online converter"
pyinstaller main.py --icon main.ico

Troubleshooting

You have your python script tested

python main.py

and you packed it into a executalbe. You doube click the executable but it just crashed. Welcome to toubleshooting.
In a GUI os, double clicking the executable(.exe) has no help for debugging. You can execute your program in a commandline in order to see the messages printing to standard output. Here are some common errors for a executable packed by pyinstaller.

Detected as a malware or a virus

  • Possible reasons and work around
    • Try pack dependecies to one folder using -D flag.
    • Avoid import whole modules such as os or sys
    • Get a digital sign for .exe. Ref

ModuleNotFoundError Module not found:

You are sure that the module is definitely imported in main.py, but the module is missed no matter how many times you have repack the script to a executable.

C:/Users/usr1/Documents/python_code>python main.py
...
...
ModuleNotFoundError: No module named 'win32timezone'

This is because the pyinstaller didn't statically import the module, you have to tell it for a force import.
Solution: After you have pack your script, you should see a file main.spec. Edit that file, find the following patterns and add the module to hiddenimports.

a = Analysis(['main.py'],
           pathex=['C:\\Users\\usr1\\Documents\\python_code'],
           binaries=[],
           datas=[],
           hiddenimports=[‘win32timezone’],
           hookspath=[],
           runtime_hooks=[],

Clean the binraries from last build(pack) by deleting the folder ./build and ./list
Before pyinstaller generates the executable according to the spec file you just edit:

pyinstaller .\main.spec # Can also be combined with options mentioned above

Then you should see your module-well-imported executalbe.

Note that every time executing pyinstaller main.py generates a main.spec, which overwrites the one in the file system.

RecursionError Maximum recursion depth exceeded

C:/Users/usr1/Documents/python_code>python main.py
...
...
RecursionError: maximum recursion depth exceeded

I don't know what is this error stands for, maybe it's about the call stack layers, but I do have a solution.
Edit main.spec, insert two lines

# -*- mode: python ; coding: utf-8 -*-
import sys                      # inserted
sys.setrecursionlimit(9000000)  # inserted, set the value that fits your need
...

Clean the binraries from last build(pack) by deleting the folder ./build and ./list.
Before pyinstaller generates the executable according to the spec file you just edit:

pyinstaller .\main.spec # Can also be combined with options mentioned above

Then you should see your recursion-limit executalbe.

Note that every time executing pyinstaller main.py generates a main.spec, which overwrites the one in the file system.