From 35d9cdb65625120c9033b2f7ee0e238759dd004e Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 8 Mar 2023 01:15:53 +0100 Subject: [PATCH] Reworked Python initialization KLAYOUT_PYTHONPATH is copied into PYTHONPATH, so it is essentially equivalent (no more copying of internally generated paths). The installation's pymod folder is added to the path, so that we can put "klayout.db" etc. there. --- src/pya/pya/pya.cc | 63 +++++++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 23 deletions(-) diff --git a/src/pya/pya/pya.cc b/src/pya/pya/pya.cc index 46f452fe3..9da57b0d2 100644 --- a/src/pya/pya/pya.cc +++ b/src/pya/pya/pya.cc @@ -34,6 +34,7 @@ #include "gsiDecl.h" #include "gsiDeclBasic.h" #include "tlLog.h" +#include "tlEnv.h" #include "tlStream.h" #include "tlTimer.h" #include "tlFileUtils.h" @@ -223,21 +224,42 @@ PythonInterpreter::PythonInterpreter (bool embedded) std::string app_path = tl::get_exe_file (); -#if PY_MAJOR_VERSION >= 3 + // If set, use $KLAYOUT_PYTHONPATH to initialize the path. + // Otherwise there may be some conflict between external installations and KLayout. - // if set, use $KLAYOUT_PYTHONPATH to initialize the path -# if defined(_WIN32) + bool has_klayout_pythonpath = false; + + // Python is not easily convinced to use an external path properly. + // So we simply redirect PYTHONPATH + std::string pythonpath_name ("PYTHONPATH"); + std::string klayout_pythonpath_name ("KLAYOUT_PYTHONPATH"); + if (tl::has_env (pythonpath_name)) { + tl::unset_env (pythonpath_name); + } + if (tl::has_env (klayout_pythonpath_name)) { + has_klayout_pythonpath = true; + tl::set_env (pythonpath_name, tl::get_env (klayout_pythonpath_name)); + } + + // If set, use $KLAYOUT_PYTHONHOME to initialize the path. + // Otherwise there may be some conflict between external installations and KLayout. + + // Python is not easily convinced to use an external path properly. + // So we simply redirect PYTHONHOME + std::string pythonhome_name ("PYTHONHOME"); + std::string klayout_pythonhome_name ("KLAYOUT_PYTHONHOME"); + if (tl::has_env (pythonhome_name)) { + tl::unset_env (pythonhome_name); + } + if (tl::has_env (klayout_pythonhome_name)) { + tl::set_env (pythonhome_name, tl::get_env (klayout_pythonhome_name)); + } + +#if defined(_WIN32) && PY_MAJOR_VERSION >= 3 tl_assert (sizeof (wchar_t) == 2); - Py_SetPythonHome ((wchar_t *) L""); // really ignore $PYTHONHOME + without this, we get dummy error message about lacking path for libraries - - const wchar_t *python_path = _wgetenv (L"KLAYOUT_PYTHONPATH"); - if (python_path) { - - Py_SetPath (python_path); - - } else { + if (! has_klayout_pythonpath) { // If present, read the paths from a file in INST_PATH/.python-paths.txt. // The content of this file is evaluated as an expression and the result @@ -289,18 +311,6 @@ PythonInterpreter::PythonInterpreter (bool embedded) } -# else - - const char *python_path = getenv ("KLAYOUT_PYTHONPATH"); - if (python_path) { - - std::wstring path = tl::to_wstring (tl::to_string_from_local (python_path)); - Py_SetPath (path.c_str ()); - - } - -# endif - #endif #if PY_MAJOR_VERSION < 3 @@ -366,6 +376,13 @@ PythonInterpreter::PythonInterpreter (bool embedded) m_pya_module.reset (new pya::PythonModule ()); m_pya_module->init (pya_module_name, module); m_pya_module->make_classes (); + + // Add a reference to the "pymod" directory close to our own library. + // We can put build-in modules there. + std::string module_path = tl::get_module_path ((void *) &reset_interpreter); + if (! module_path.empty ()) { + add_path (tl::combine_path (tl::absolute_path (module_path), "pymod")); + } } PythonInterpreter::~PythonInterpreter ()