Hello, everyone, I am the talented brother.

Pyinstaller -f tool. Py command in the command line after the success of the package, exe executable file when various errors were reported.

Today, we will share the experience of stepping on pits.

[TOC]

1. Install pyinstaller

PyInstaller is a third-party package used to package Python programs into a standalone executable.

As it is a third-party package, it needs to be installed:

pip install pyinstaller
Copy the code

Or upgrade to the latest version:

pip install --upgrade pyinstaller
Copy the code

Or install the developer version:

pip install https://github.com/pyinstaller/pyinstaller/archive/develop.tar.gz
Copy the code

Of course, you can also download the WHL file and install PIP

For more information, please refer to the official guidelines:

www.pyinstaller.org/downloads.h…

2. Pack your first experience

Let’s simply try packaging Python code as an exe executable. The test code is as follows:

# test. Py
import os

path = os.getcwd()
print(F 'Current file path:{path}')
os.system('pause')
Copy the code

This code is the directory to print the file, we use PyInstaller to package the command as follows:

Pyinstaller -f test.pyCopy the code

The procedure for executing this command is as follows:

(env_test) F:\PythonCool\ PyInstaller > PyInstaller -f. py 403 INFO: pyInstaller: 4.3 403 INFO: Python: 3.8.10 (conda) 434 INFO: Platform: Windows-10-10.0.19042-sp0 436 INFO: Wrote F:\PythonCool\ PyInstaller \ test. spec 455 INFO: UPX is not available. 468 INFO: Extending PYTHONPATH with paths ['F:\\PythonCool\\pyinstaller'.'F:\\PythonCool\\pyinstaller'] 501 INFO: checking Analysis ... . 15006 INFO: Appending Archive to EXE F:\PythonCool\ PyInstaller \dist\ test. EXE 18999 INFO: Building EXE from EXE-00.toc completed successfully.Copy the code

On success, a dist file is generated in the parent directory, which contains an executable file with the same name as the file name:

Double-click on the executable and we can see the same result when we run the test.py file directly from the Python interpreter:

Note that we need to specify the path of the py file to be packed when packaging. There are two ways to choose:

Method 1: Switch to the directory of the py file to be packed first, and then execute the packing command

(base) C:\Users\Gdc>cdF:\PythonCool\ PyInstaller (base) C:\Users\Gdc>F: \PythonCool\ PyInstaller > PyInstaller -f test.pyCopy the code

Method 2: Specify the absolute path of the py file in the package directive

(base) C:\Users\Gdc> PyInstaller -f F:\PythonCool\ PyInstaller \ test.pyCopy the code

Regarding the successfully packaged test.exe executable, we found that its icon is default and a command line window is displayed on startup. So how can we customize the exe icon, or get rid of the command line window?

3. Package an advanced experience

Now, let’s take a look at some of the other parameters for pyInstaller packaging, how to customize the exe icon, how to remove the command line window, etc.

(env_test) F:\PythonCool\pyinstaller>pyinstaller -h
Copy the code

Pyinstaller -h can be used to view its parameters. This section describes some common parameters.

parameter instructions
-F Produces a single executable file
-D Produces a directory (containing multiple files) as an executable program
-a Unicode character set support is not included
-d Debug Version of the executable file
-w Specifies that the program runs without a command line window (Windows only)
-c Specifies the use of a command line window to run the program (Windows only)
-o Specify the build directory for the spec file. If not specified, the current directory is used to generate the spec file by default
-p Set the path to which Python imports modules (similar to setting the PYTHONPATH environment variable). You can also use path separators (Windows uses semicolons, Linux uses colons) to separate multiple paths
-n Specify the project (generated spec) name. If this option is omitted, the main file name of the first script is the name of the spec

Package an exe executable with a custom icon

We can download the icon file here:

www.iconfont.cn/

To convert an image into an icon file, go here:

www.bitbug.net/

Then, you can customize the exe icon with the following command:

(env_test) F:\PythonCool\ PyInstaller > pyInstaller -f -i icon.ico test.pyCopy the code

After success, we can see the icon changed to our custom one:

Package the exe executable with the command line popover removed

If we are a GUI application and want to remove the command line window at startup, we can package it with the following command. Here is an example of tkinter’s built-in GUI library:

# test. Py
import tkinter

top = tkinter.Tk()
Enter the message loop
top.mainloop()
Copy the code

The above test code, if used in the initial experience, will appear in the GUI interface at the same time the command line popover, we want to remove the command line popover can:

(env_test) F:\PythonCool\ PyInstaller > pyInstaller -f -w -i icon. pyCopy the code

Double-click the packaged EXE file, you can see that only the GUI interface appears, the command line window does not appear.

4. Pack the configuration file

Packaging with configuration files means that there are other resource files that need to be referenced in addition to py files and dependent libraries. These resources cannot be included in the package when the package is directly packaged in the above way. We need to modify the spec file in the package to achieve this.

Spec files tell Pyinstaller how to package PY files, such as paths, resources, dynamic libraries, implicitly called modules, etc. In general, we don’t need to modify it…

Here I use the previous “word cloud drawing gadget” case to introduce.

We can successfully package using the command in the packaging Advanced experience, but here we find two problems: (1) The package is very large, about 10 times larger than the previous case; ② An error occurred when starting the EXE file.

For larger packages, try creating a virtual environment and installing only the libraries that need to be called in the program. Here’s a brief introduction:

Create a virtual environmentConda create -n your_env_name python=3.8.10Start the virtual environment
activate your_env_name
Copy the code

About the startup error, because it is complicated, let’s look at it step by step:

① Since there is no command line popup, we can’t see the specific error message. Here we go to the form of command line window to see the error message. We see the error as follows:

Note that this file is missing, we can put this resource in the package generated word cloud drawing tool. Spec configuration file

# -*- mode: python ; coding: utf-8 -*-
# word cloud drawing tool.spec

block_cipher = None

a = Analysis(['Word cloud drawing tool.py'],
             pathex=['F:\\PythonCool\\pyinstaller'],
             binaries=[],
             datas=[], Add the resource file address here
             hiddenimports=[], # Dynamically imported libraries or modules
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          [],
          name='Word Cloud Drawing Tool',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          upx_exclude=[],
          runtime_tmpdir=None,
          console=True , icon='icon.ico')
Copy the code

By looking up the StopWords file in the WordCloud module directory, we put it in data.

datas=[('C:\\Users\\Gdc\\anaconda3\\envs\\env_test\\Lib\\site-packages\\wordcloud\\stopwords'.'wordcloud')].Add the resource file address here
Copy the code

The former is the local location of the resource file, and the latter is the relative path of the packaged file. After editing the spec file, package it with the following command:

(env_test) F:\PythonCool\ PyInstaller > PyInstaller -d. SpecCopy the code

Well, there are still some files that haven’t been bagged, so we have the same problem again. Therefore, we need to add all resource files to the data in the spec file.

Let’s find all the resource files and add them all, and then execute the package command.

datas=[('C:\\Users\\Gdc\\anaconda3\\envs\\env_test\\Lib\\site-packages\\stylecloud\\static'.'stylecloud\\static'),
    ('C:\\Users\\Gdc\\anaconda3\\envs\\env_test\\Lib\\site-packages\\wordcloud\\stopwords'.'wordcloud'),
    ('C:\\Users\\Gdc\\anaconda3\\envs\\env_test\\Lib\\site-packages\\jieba\\analyse\\idf.txt'.'jieba\\analyse'),
    ('C:\\Users\\Gdc\\anaconda3\\envs\\env_test\\Lib\\site-packages\\jieba\\dict.txt'.'jieba')]
Copy the code

We can start the EXE executable normally after we put the configuration resources into the package.

However, it is also found that there will be an error when performing word cloud rendering. Xx module does not exist, so what is the case? !

5. Add implicit invocation libraries

The code where we found the error was as follows, using the __import__() function for dynamically loading the class and function palettable module.

def gen_palette(palette: str) :
    """Generates the corresponding palette function from `palettable`."""
    palette_split = palette.split(".")
    palette_name = palette_split[-1]

    # https://stackoverflow.com/a/6677505
    palette_func = getattr(
        __import__(
            "palettable.{}".format(".".join(palette_split[:-1])),
            fromlist=[palette_name],
        ),
        palette_name,
    )
    return palette_func
Copy the code

For this problem, I have tried two solutions, for your reference.

Option 1: Add dynamically referenced modules to hiddenImports in the Spec file

hiddenimports=['palettable'].# Dynamically imported libraries or modules
Copy the code

In this case, the PaletTable also has some configuration files that need to be added to the data in the spec file

('C:\\Users\\Gdc\\anaconda3\\envs\\env_test\\Lib\\site-packages\\palettable\\colorbrewer\\data'.'palettable\\colorbrewer\\data')
Copy the code

Option 2: Modify the stylecloud library to call the Palettable module code part

import palettable
def gen_palette(palette: str) :
    palette_func = getattr(palettable.tableau,'BlueRed_6')
    return palette_func
 
    # """Generates the corresponding palette function from `palettable`."""
    # palette_split = palette.split(".")
    # palette_name = palette_split[-1]

    # https://stackoverflow.com/a/6677505
    # palette_func = getattr(
        # __import__(
            # "palettable.{}".format(".".join(palette_split[:-1])),
            # fromlist=[palette_name],
        #).
        # palette_name,
    #)
Copy the code

With Parts 4 and 5, we finally packaged and worked with PyInstaller.

The above is all the content of this time, if you encounter packaging involves configuration files or implicit call, you can use these two 2 techniques for special packaging!

However, there is more to pyInstaller packaging, which you can learn from the official documentation, including the command line parameters and the spec file.