Fix Windows FastAPI import: Replace collect_all with collect_submodules
Research findings: - collect_all() has design flaws and poor performance with pydantic - Pydantic uses compiled cpython extensions that prevent module discovery - collect_submodules() is the recommended approach per PyInstaller docs Changes: - Replaced collect_all() with collect_submodules() for better reliability - Now collects 105 pydantic submodules (vs unreliable collect_all) - Added collect_data_files() for packages requiring data files - Added explicit pydantic dependencies: colorsys, decimal, json, etc. - Applies to both Windows AND Linux (no longer platform-specific) Results: ✓ Collected 52 submodules from fastapi ✓ Collected 34 submodules from starlette ✓ Collected 105 submodules from pydantic ✓ Collected 3 submodules from pydantic_core ✓ Plus uvicorn, websockets, h11, anyio Fixes: ModuleNotFoundError: No module named 'fastapi' on Windows Based on: https://github.com/pyinstaller/pyinstaller/issues/5359
This commit is contained in:
@@ -10,9 +10,8 @@ block_cipher = None
|
||||
# Determine if we're on Windows
|
||||
is_windows = sys.platform == 'win32'
|
||||
|
||||
# Import PyInstaller utilities (only needed on Windows for FastAPI fix)
|
||||
if is_windows:
|
||||
from PyInstaller.utils.hooks import collect_all
|
||||
# Import PyInstaller utilities
|
||||
from PyInstaller.utils.hooks import collect_submodules, collect_data_files
|
||||
|
||||
# Find faster_whisper assets folder
|
||||
import faster_whisper
|
||||
@@ -82,20 +81,34 @@ hiddenimports = [
|
||||
'charset_normalizer',
|
||||
]
|
||||
|
||||
# On Windows, use more aggressive collection for FastAPI packages
|
||||
# This fixes import errors on Windows while keeping Linux builds stable
|
||||
if is_windows:
|
||||
print("Windows build: Using collect_all for FastAPI packages...")
|
||||
for package in ['fastapi', 'starlette', 'pydantic', 'pydantic_core', 'anyio', 'uvicorn', 'websockets', 'h11']:
|
||||
# Collect all submodules for FastAPI and related packages
|
||||
# This approach is more reliable than collect_all() which has design flaws
|
||||
# Particularly important for pydantic which uses compiled cpython extensions
|
||||
print("Collecting submodules for FastAPI packages...")
|
||||
for package in ['fastapi', 'starlette', 'pydantic', 'pydantic_core', 'anyio', 'uvicorn', 'websockets', 'h11', 'httptools', 'uvloop']:
|
||||
try:
|
||||
tmp_datas, tmp_binaries, tmp_hiddenimports = collect_all(package)
|
||||
datas += tmp_datas
|
||||
binaries += tmp_binaries
|
||||
hiddenimports += tmp_hiddenimports
|
||||
print(f" ✓ Collected {package}")
|
||||
submodules = collect_submodules(package)
|
||||
hiddenimports += submodules
|
||||
print(f" ✓ Collected {len(submodules)} submodules from {package}")
|
||||
except Exception as e:
|
||||
print(f" ⚠ Warning: Could not collect {package}: {e}")
|
||||
|
||||
# Collect data files for packages that need them
|
||||
for package in ['fastapi', 'starlette', 'pydantic', 'uvicorn']:
|
||||
try:
|
||||
data_files = collect_data_files(package)
|
||||
if data_files:
|
||||
datas += data_files
|
||||
print(f" ✓ Collected {len(data_files)} data files from {package}")
|
||||
except Exception as e:
|
||||
pass # Not all packages have data files
|
||||
|
||||
# Add critical pydantic dependencies that may be missed
|
||||
hiddenimports += [
|
||||
'colorsys', 'decimal', 'json', 'ipaddress', 'pathlib', 'uuid',
|
||||
'email.message', 'typing_extensions',
|
||||
]
|
||||
|
||||
a = Analysis(
|
||||
['main.py'],
|
||||
pathex=[],
|
||||
|
||||
Reference in New Issue
Block a user