Skip to content

PyInstaller bundled: get_object fails with FileNotFoundError for meanshape_68.pkl #2888

Description

@guorui999

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:

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:

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions