Information Technology Grimoire

Version .0.0.1

IT Notes from various projects because I forget, and hopefully they help you too.

python3 Compile with PyInstaller

Setup your venv

python -m venv someprogram
cd someprogram
scripts\activate
python -m pip install -r requirements.txt

Assumptions

We are going to assume there are several files in the same directory such as:

  • main.py
  • config.py
  • database.py
  • gui.py
  • image_processing.py
  • models.py
  • pdf_generation.py

We will further assume that you start the program with the entry point of main.py such as:

python main.py

My particular program above also had image files and a database file, also in the same directory. This compilation did not include them, so I need to provide them with the executable it makes.iter

Install “PyInstaller”

pip install pyinstaller

Create app.spec

The .spec file can be named anything. It must end with .spec though. Note you must modify it to match your existing project, including subfolders. Extra files like images, databases, etc are not included in the compilation.

# -*- mode: python ; coding: utf-8 -*-

# Encryption type for code - None means no encryption
block_cipher = None

# Main Analysis object that finds all dependencies
a = Analysis(
    ['main.py'],  # Entry point script
    pathex=[],    # Additional paths to search for imports
    binaries=[],  # Additional binary files (.dll, .so)
    datas=[       # Non-Python files to include
        ('config.py', '.'),      # Source file -> destination directory
        ('database.py', '.'),    # '.' means same directory as exe
        ('gui.py', '.'),
        ('image_processing.py', '.'),
        ('models.py', '.'),
        ('pdf_generation.py', '.')
    ],
    hiddenimports=['PIL', 'ttkbootstrap', 'fpdf'],  # Imports PyInstaller might miss
    hookspath=[],      # Custom PyInstaller hooks
    hooksconfig={},    # Configuration for hooks
    runtime_hooks=[],  # Scripts to run before frozen app
    excludes=[],       # Modules to ignore
    win_no_prefer_redirects=False,   # Windows-specific redirect behavior
    win_private_assemblies=False,    # Windows DLL handling
    cipher=block_cipher,    # Encryption settings
    noarchive=False        # Whether to embed Python bytecode
)

# Creates a Python executable archive
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)

# Creates the final executable
exe = EXE(
    pyz,                    # Include the PYZ archive
    a.scripts,              # Scripts to include
    a.binaries,            # Binary dependencies
    a.zipfiles,            # Zipped Python modules
    a.datas,               # Data files
    [],                    # Additional files to include
    name='YogaFlow',       # Name of output executable
    debug=False,           # Include debug info
    bootloader_ignore_signals=False,  # Signal handling
    strip=False,           # Strip debug symbols
    upx=True,             # Use UPX compression
    upx_exclude=[],        # Files to not compress
    runtime_tmpdir=None,   # Temp directory at runtime
    console=False,         # GUI mode (no console window)
    disable_windowed_traceback=False,  # Error handling
    target_arch=None,      # Target architecture
    codesign_identity=None,  # Code signing (macOS)
    entitlements_file=None   # macOS entitlements
)
pyinstaller app.spec

Get the exe

My actual exe is now located and created in the ./dist folder. Your friends do not need to install venv anymore, they can just run the exe.

Signing

Signing alerts (unsigned binary) might give an error when your friend runs the program. You can get around this and not show the error by purchasing a code signing certificate for between $100-$1000 a year. If you have purchased this cert, then you can sign your executable:

signtool sign /tr http://timestamp.digicert.com /td sha256 /fd sha256 /f "YourCertificate.pfx" /p YourPassword "dist\yourapp.exe"

https://learn.microsoft.com/en-us/windows/win32/seccrypto/signtool

Last updated on 8 Feb 2025
Published on 8 Feb 2025