SoFunction
Updated on 2025-05-12

Several common ways to include font library files when packaging Python

Preface

When packaging Python, if you want to package font files (such as .ttf, .otf, etc.) into an executable file together, there are several common methods, depending on the packaging tool you are using.

Using PyInstaller

PyInstaller is one of the most commonly used packaging tools, and the following is a method that contains font library files:

1. Basic method - Use --add-data parameters:

pyinstaller --onefile --add-data=";." your_script.py

Multiple:

pyinstaller --onefile --add-data=":." --add-data=":." --add-data="fonts/:fonts/" your_script.py

2. Use spec files (more recommended):

  • First generate the spec file:pyi-makespec your_script.py

  • Then modify the spec file, inAdd font files to:

a = Analysis(
    ['your_script.py'],
    binaries=[],
    datas=[('', '.')],  # Add this line    ...
)

Add multiple files

a = Analysis(
    ['your_script.py'],
    binaries=[],
    datas=[
        ('', '.'),
        ('', '.'),
        ('fonts/', 'fonts'),  # Keep the directory structure        ('fonts/', 'fonts'),
    ],
    ...
)

Need to process the font path in the code:

import os
import sys

def resource_path(relative_path):
    """Absolute path to obtain resources"""
    if hasattr(sys, '_MEIPASS'):
        return (sys._MEIPASS, relative_path)
    return (("."), relative_path)

#User Examplefont_path = resource_path("")

Things to note

  • Make sure to correctly reference the font file path in the code (using the aboveresource_pathmethod)

  • If the font file is larger, the packaged file volume will increase significantly.

  • Test whether the packaged program can load fonts correctly

  • Consider the font file's license issue and make sure you have the right to distribute the font

Which method to choose depends on your specific needs and the packaging tool you use. PyInstaller is usually the best choice for cross-platform packaging.

3. Add font folders in batches

import glob

# Get all font filesfont_files = ('fonts/*.ttf') + ('fonts/*.otf')

a = Analysis(
    ['your_script.py'],
    binaries=[],
    datas=[(font, 'fonts') for font in font_files],
    ...
)

Things to note

  • Keep the file directory structure consistent, especially when fonts are referenced in the code

  • Check the font file license to make sure it can be distributed legally

  • A large number of font files will significantly increase the volume after packaging

  • Test whether the packaged program can correctly find and load all fonts

  • Consider using relative paths instead of absolute paths to refer to font files

Which method to choose depends on your project requirements and the packaging tools you use. For most cases, PyInstaller's spec file approach provides the best flexibility and maintainability.

4. Package with spec files

pyinstaller your_script.spec

5. Access the packaged font file in the code

import os
import sys
from pathlib import Path

def resource_path(relative_path):
    """ Obtain the absolute path to the packaged resource"""
    if hasattr(sys, '_MEIPASS'):
        base_path = Path(sys._MEIPASS)
    else:
        base_path = ()
    return str(base_path / relative_path)

#User Examplefont_path = resource_path('fonts/')

# Use fonts (taking Pillow as an example)from PIL import ImageFont
try:
    font = (font_path, size=12)
except IOError:
    print(f"Unable to load font file: {font_path}")
    font = ImageFont.load_default()

Summarize

This is the end of this article about several common methods for including font library files when packaging Python. For more related Python packages, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!