#[cfg(not(any(PyPy, GraalPy)))]
use crate::{ffi, internal::state::AttachGuard, Python};
static START: std::sync::Once = std::sync::Once::new();
#[cfg(not(any(PyPy, GraalPy)))]
pub(crate) fn initialize() {
START.call_once_force(|_| unsafe {
if ffi::Py_IsInitialized() == 0 {
ffi::Py_InitializeEx(0);
ffi::PyEval_SaveThread();
}
});
}
#[cfg(not(any(PyPy, GraalPy)))]
pub unsafe fn with_embedded_python_interpreter<F, R>(f: F) -> R
where
F: for<'p> FnOnce(Python<'p>) -> R,
{
assert_eq!(
unsafe { ffi::Py_IsInitialized() },
0,
"called `with_embedded_python_interpreter` but a Python interpreter is already running."
);
unsafe { ffi::Py_InitializeEx(0) };
let result = {
let guard = unsafe { AttachGuard::assume() };
let py = guard.python();
py.import("threading").unwrap();
f(py)
};
unsafe { ffi::Py_Finalize() };
result
}
pub(crate) fn wait_for_initialization() {
START.call_once(|| {
assert_ne!(unsafe { crate::ffi::Py_IsInitialized() }, 0);
});
}
pub(crate) fn ensure_initialized() {
#[cfg(all(feature = "auto-initialize", not(any(PyPy, GraalPy))))]
{
initialize();
}
#[cfg(not(all(feature = "auto-initialize", not(any(PyPy, GraalPy)))))]
{
#[cfg(not(any(PyPy, GraalPy)))]
if option_env!("CARGO_PRIMARY_PACKAGE").is_some() {
initialize();
}
START.call_once_force(|_| unsafe {
assert_ne!(
crate::ffi::Py_IsInitialized(),
0,
"The Python interpreter is not initialized and the `auto-initialize` \
feature is not enabled.\n\n\
Consider calling `Python::initialize()` before attempting \
to use Python APIs."
);
});
}
}