PyInstaller bundled: get_object fails with FileNotFoundError for meanshape_68.pkl

Author: guorui999Created Jun 18, 2026Updated Jul 31, 2026

Bug: get_object uses sys._MEIPASS which doesn't contain objects/ in PyInstaller builds

Version

insightface 1.0.1

Steps to Reproduce

  1. Build a PyInstaller executable that imports insightface (e.g. using --collect-all insightface)
  2. Run the bundled executable
  3. Create a FaceAnalysis instance with allowed_modules=["recognition", "detection", "genderage", "landmark_3d_68", "landmark_2d_106"] or just name="buffalo_l"

Expected Behavior

The landmark models load successfully. meanshape_68.pkl is found and deserialized.

Actual Behavior

The application prints:

[Error] File not found: <TEMP_DIR\_MEIxxxxxx\objects\meanshape_68.pkl>

and the Landmark model initialization fails silently (returns None), leading to cascading AttributeError when app.get() returns faces with landmark_3d_68 = None:

AttributeError: 'NoneType' object has no attribute 'shape'

Root Cause

In insightface/data/pickle_object.py, the get_object() function:

python
def get_object(name):
    if getattr(sys, 'frozen', False):
        base_dir = sys._MEIPASS   # <-- Problem: _MEIPASS is PyInstaller's temp dir
    else:
        base_dir = Path(__file__).parent.absolute()  # insightface/data/

    objects_dir = osp.join(base_dir, 'objects')  # → _MEIPASS/objects/ (EMPTY!)
    # The actual PKL is at insightface/data/objects/meanshape_68.pkl

When sys.frozen is True (PyInstaller), it uses sys._MEIPASS as the base directory. However, sys._MEIPASS points to the temporary extracted directory (e.g. C:\Users\...\AppData\Local\Temp\_MEIxxxxxx\), which does **not** contain the objects/ subdirectory. The PKL file lives at site-packages/insightface/data/objects/meanshape_68.pkl.

In contrast, the non-frozen path correctly uses Path(__file__).parent.absolute() which resolves to insightface/data/, where objects/ actually exists.

Proposed Fix

Option A — fall back to the package-relative path:

python
def get_object(name):
    objects_dirs = []
    if getattr(sys, 'frozen', False):
        objects_dirs.append(sys._MEIPASS)
    objects_dirs.append(str(Path(__file__).parent.absolute()))

    if not name.endswith('.pkl'):
        name = name + ".pkl"

    for base_dir in objects_dirs:
        filepath = osp.join(base_dir, 'objects', name)
        if osp.exists(filepath):
            with open(filepath, 'rb') as f:
                return pickle.load(f)

    print(f"[Error] File not found: objects/{name}")
    return None

Option B — use importlib.resources for the fallback path.

Environment

  • Python: 3.12
  • insightface: 1.0.1
  • OS: Windows 11
  • PyInstaller: bundled via --collect-all insightface