| 189 | } |
| 190 | |
| 191 | void mitk::PythonContext::ExecuteFile(const fs::path& filePath) |
| 192 | { |
| 193 | const auto normalizedPath = fs::absolute(filePath).lexically_normal(); |
| 194 | |
| 195 | std::ifstream stream(normalizedPath, std::ios::binary); |
| 196 | |
| 197 | if (!stream.is_open()) |
| 198 | mitkThrow() << "Could not open Python file: " << normalizedPath.string(); |
| 199 | |
| 200 | std::ostringstream buffer; |
| 201 | buffer << stream.rdbuf(); |
| 202 | |
| 203 | py::gil_scoped_acquire gil; |
| 204 | |
| 205 | // __file__ and __name__ are script-scoped: the guards below insert them |
| 206 | // for the duration of execution so scripts can use Path(__file__) and |
| 207 | // `if __name__ == "__main__"`, then remove them on destruction so |
| 208 | // subsequent Execute() calls don't see stale values. User-defined |
| 209 | // globals intentionally persist in the shared dictionary. |
| 210 | ScopedDictKey fileKey(m_Impl->Dictionary, "__file__", |
| 211 | py::str(normalizedPath.generic_string())); |
| 212 | ScopedDictKey nameKey(m_Impl->Dictionary, "__name__", |
| 213 | py::str("__main__")); |
| 214 | |
| 215 | try |
| 216 | { |
| 217 | py::exec(buffer.str(), m_Impl->Dictionary); |
| 218 | } |
| 219 | catch (py::error_already_set& e) |
| 220 | { |
| 221 | mitkThrow() << "An error occurred while executing Python file \"" |
| 222 | << normalizedPath.string() << "\": " << e.what(); |
| 223 | } |
| 224 | } |
| 225 | |
| 226 | void mitk::PythonContext::BindImage(Image* image, const std::string& varName) |
| 227 | { |