1. Using Spec Files

When you execute

pyinstaller options.. main.py

You can also create a spec file using this command:

pyi-makespec options [other scripts …]name.py

the first thing PyInstaller does is to build a spec (specification) file main.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 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 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 ( or files) that PyInstaller does not know about from any other source..dll.so
  • When you want to add Python run-time options to the executable.
  • When you want to create a multiprogram bundle with merged common modules.

2. Spec File Operation

After PyInstaller creates a spec file, or opens a spec file when one is given instead of a script, the 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(...)

3. Adding Data Files

You can add your python files like

a = Analysis(['1.py','2.py',...],...)

And add your Resource files, provide a list that describes the files as the value of the argument to . 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.
    datas=[("resource", "resource"),...]
    

4. Important “pathex”

A list of paths to search for imports (like using PYTHONPATH), including paths given by the –paths option.

Please write here as many paths as possible.

For example, my folder schema looks like

MyFolder
    venv
        Lib
            site-packages
        Scripts
    main.py

The venv folder is a Python3.8.10 virtual environment. When you often encounter DLLs or module errors when packaging, try to add all the paths you can think of.

pathex=['.\MyFolder',
    '.\MyFolder\venv\Scripts',
    '.\MyFolder\venv\Lib\site-packages',
    '.\MyFolder\venv\Lib\site-packages\PyQt5',
    '.\MyFolder\venv\Lib\site-packages\PyQt5\Qt5\bin',
    '\MyFolder\venv\Lib\site-packages\PyQt5\Qt5\plugins\platforms',
    ],

5. Window Icon

To avoid losing the icon in the upper left corner of the GUI window after packaging, you should change some codes.

Place “ico.png” into the “ico” folder.

Change icon path to the icon file directory in the exe runtime temporary directory.

1
2
3
4
5
6
def resource_path(self, relative_path):
if hasattr(sys, '_MEIPASS'):
base_path = sys._MEIPASS # 只有通过exe运行时才会进入这个分支,它返回的是exe运行时的临时目录路径
else:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)

Set icon path.

1
2
icon = self.resource_path(os.path.join("ico", "ico.png"))
self.setWindowIcon(QtGui.QIcon(icon))

Add datas in the spec file.

1
datas=[("ico", "ico")],

Run pyinstaller in Terminal in the last.