| 637 | } |
| 638 | |
| 639 | void ensure_initialized() { |
| 640 | call_once_py_init([] { |
| 641 | if (!Py_IsInitialized()) { |
| 642 | PyImport_AppendInittab("_lfs_output", init_capture_module); |
| 643 | |
| 644 | PyConfig config; |
| 645 | PyConfig_InitPythonConfig(&config); |
| 646 | config.user_site_directory = 0; |
| 647 | |
| 648 | const auto python_home = lfs::core::getPythonHome(); |
| 649 | if (!python_home.empty()) { |
| 650 | const auto home_wstr = python_home.wstring(); |
| 651 | PyStatus st = PyConfig_SetString(&config, &config.home, home_wstr.c_str()); |
| 652 | if (PyStatus_Exception(st)) { |
| 653 | LOG_ERROR("Failed to set Python home: {}", st.err_msg ? st.err_msg : "unknown"); |
| 654 | PyConfig_Clear(&config); |
| 655 | return; |
| 656 | } |
| 657 | LOG_INFO("Set Python home: {}", lfs::core::path_to_utf8(python_home)); |
| 658 | } |
| 659 | |
| 660 | PyStatus status = Py_InitializeFromConfig(&config); |
| 661 | PyConfig_Clear(&config); |
| 662 | if (PyStatus_Exception(status)) { |
| 663 | LOG_ERROR("Failed to initialize Python: {}", |
| 664 | status.err_msg ? status.err_msg : "unknown"); |
| 665 | return; |
| 666 | } |
| 667 | |
| 668 | g_we_initialized_python = true; |
| 669 | LOG_INFO("Python interpreter initialized by application"); |
| 670 | } else { |
| 671 | LOG_WARN("Python already initialized by external code (e.g., .pyd loading)"); |
| 672 | g_we_initialized_python = false; |
| 673 | } |
| 674 | |
| 675 | register_output_module_post_init(); |
| 676 | |
| 677 | // Add user site-packages to sys.path |
| 678 | std::filesystem::path user_packages = get_user_packages_dir(); |
| 679 | if (!std::filesystem::exists(user_packages)) { |
| 680 | std::error_code ec; |
| 681 | std::filesystem::create_directories(user_packages, ec); |
| 682 | if (ec) { |
| 683 | LOG_WARN("Failed to create user packages dir: {}", ec.message()); |
| 684 | } |
| 685 | } |
| 686 | |
| 687 | PyObject* sys_path = PySys_GetObject("path"); |
| 688 | if (sys_path) { |
| 689 | prepend_sys_path_once(sys_path, user_packages, "user packages dir"); |
| 690 | |
| 691 | const auto python_module_dir = lfs::core::getPythonModuleDir(); |
| 692 | if (!python_module_dir.empty()) { |
| 693 | prepend_sys_path_once(sys_path, python_module_dir, "Python module dir"); |
| 694 | } else { |
| 695 | const auto exe_dir_utf8 = lfs::core::path_to_utf8(lfs::core::getExecutableDir()); |
| 696 | LOG_WARN("Python module 'lichtfeld' not found. Expected a lichtfeld*.so/.pyd in: {}/src/python, {}", |