From e56dc20215c40a8355fcb294fac1331f95653757 Mon Sep 17 00:00:00 2001 From: Antti Soininen Date: Thu, 22 Feb 2024 12:27:03 +0200 Subject: [PATCH] Add support for PyInstaller bundles Location of the embedded Python installer in a bundle is different between cx_Freeze and PyInstaller. --- spine_engine/config.py | 30 ++++++++++++++++++++++++++++-- spine_engine/utils/helpers.py | 11 +++++------ 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/spine_engine/config.py b/spine_engine/config.py index af4dc3a3..e9638be4 100644 --- a/spine_engine/config.py +++ b/spine_engine/config.py @@ -35,12 +35,38 @@ def _executable(name): JULIA_EXECUTABLE = _executable("julia") # Python +def is_frozen(): + """Checks if we are currently running as frozen bundle. + + Returns: + bool: True if we are frozen, False otherwise + """ + return getattr(sys, "frozen", False) + + +def is_pyinstaller_bundle(): + """Checks if we are in a PyInstaller bundle. + + Returns: + bool: True if the current bundle has been build by PyInstaller, False otherwise + """ + return hasattr(sys, "_MEIPASS") + + PYTHON_EXECUTABLE = _executable("python" if _on_windows else "python3") _frozen = getattr(sys, "frozen", False) _path_to_executable = os.path.dirname(sys.executable if _frozen else __file__) APPLICATION_PATH = os.path.realpath(_path_to_executable) -# Experimental Python interpreter shipped with Spine Toolbox installation bundle -EMBEDDED_PYTHON = os.path.join(APPLICATION_PATH, "tools", "python.exe") +# Python interpreter shipped with bundle +BUNDLE_DIR = "Python" +if is_frozen(): + if is_pyinstaller_bundle(): + EMBEDDED_PYTHON = os.path.join(sys._MEIPASS, BUNDLE_DIR, PYTHON_EXECUTABLE) + else: + EMBEDDED_PYTHON = os.path.join(APPLICATION_PATH, BUNDLE_DIR, PYTHON_EXECUTABLE) +else: + EMBEDDED_PYTHON = None + # Tool output directory name TOOL_OUTPUT_DIR = "output" diff --git a/spine_engine/utils/helpers.py b/spine_engine/utils/helpers.py index 8b661c2c..dd238f73 100644 --- a/spine_engine/utils/helpers.py +++ b/spine_engine/utils/helpers.py @@ -23,7 +23,7 @@ import networkx from jupyter_client.kernelspec import find_kernel_specs from spinedb_api.spine_io.gdx_utils import find_gams_directory -from ..config import PYTHON_EXECUTABLE, JULIA_EXECUTABLE, GAMS_EXECUTABLE, EMBEDDED_PYTHON +from ..config import PYTHON_EXECUTABLE, JULIA_EXECUTABLE, GAMS_EXECUTABLE, EMBEDDED_PYTHON, is_frozen @unique @@ -128,13 +128,12 @@ def resolve_current_python_interpreter(): Returns: str: path to Python interpreter """ - if not getattr(sys, "frozen", False): - return sys.executable # Use current Python - # We are frozen + if not is_frozen(): + return sys.executable path = resolve_executable_from_path(PYTHON_EXECUTABLE) if path != "": - return path # Use Python from PATH - return EMBEDDED_PYTHON # Use embedded /Tools/python.exe + return path + return EMBEDDED_PYTHON def resolve_julia_executable(settings):