| 83 | } |
| 84 | |
| 85 | PythonEngine::PythonEngine(int argc, char* argv[]) : ScriptEngine(argc, argv), program(Py_DecodeLocale(pythonProgramName, nullptr)) { |
| 86 | // TODO: modernize and use PyConfig (new in 3.8): https://docs.python.org/3/c-api/init_config.html |
| 87 | |
| 88 | // this frozen flag tells Python that the package and library have been frozen for embedding, so it shouldn't warn about missing prefixes |
| 89 | Py_FrozenFlag = 1; |
| 90 | |
| 91 | // Path to the E+ shipped standard library |
| 92 | auto pathToPythonPackages = getEnergyPlusDirectory() / "python_lib"; |
| 93 | |
| 94 | // The PYTHONPATH / PYTHONHOME should be set before initializing Python |
| 95 | // If this Py_SetPath is called before Py_Initialize, then Py_GetPath won't attempt to compute a default search path |
| 96 | // The default search path is affected by the Py_SetPythonHome |
| 97 | // * if the user passed --python_home, we use that as the Python Home, and do not use Py_SetPath. But later we add the E+ standard_lib anyways |
| 98 | // so it takes precedence (to limit incompatibility issues...) |
| 99 | // * If the user didn't pass it, we use Py_SetPath set to the E+ standard_lib |
| 100 | |
| 101 | std::vector<std::string> args(argv, std::next(argv, static_cast<std::ptrdiff_t>(argc))); |
| 102 | bool pythonHomePassed = false; |
| 103 | auto it = std::find(args.cbegin(), args.cend(), "--python_home"); |
| 104 | if (it != args.cend()) { |
| 105 | openstudio::path pythonHomeDir(*std::next(it)); |
| 106 | wchar_t* h = Py_DecodeLocale(pythonHomeDir.make_preferred().string().c_str(), nullptr); |
| 107 | Py_SetPythonHome(h); |
| 108 | pythonHomePassed = true; |
| 109 | } else { |
| 110 | wchar_t* a = Py_DecodeLocale(pathToPythonPackages.make_preferred().string().c_str(), nullptr); |
| 111 | Py_SetPath(a); |
| 112 | } |
| 113 | |
| 114 | Py_SetProgramName(program); // optional but recommended |
| 115 | |
| 116 | Py_Initialize(); |
| 117 | |
| 118 | if (pythonHomePassed) { |
| 119 | addToPythonPath(pathToPythonPackages); |
| 120 | } |
| 121 | #if defined(__APPLE__) || defined(__linux___) || defined(__unix__) |
| 122 | addToPythonPath(pathToPythonPackages / "lib-dynload"); |
| 123 | #endif |
| 124 | |
| 125 | PyObject* m = PyImport_AddModule("__main__"); |
| 126 | if (m == nullptr) { |
| 127 | throw std::runtime_error("Unable to add module __main__ for python script execution"); |
| 128 | } |
| 129 | m_globalDict = PyModule_GetDict(m); |
| 130 | |
| 131 | //PyRun_SimpleString("from time import time,ctime\n" |
| 132 | // "print('Today is', ctime(time()))\n"); |
| 133 | importOpenStudio(); |
| 134 | } |
| 135 | |
| 136 | PythonEngine::~PythonEngine() { |
| 137 | if (Py_FinalizeEx() < 0) { |
nothing calls this directly
no test coverage detected