PyO3/pyo3 · critical
failed to import `datetime` C API
Error message
failed to import `datetime` C API
What it means
PyO3's `datetime` support caches a pointer to the CPython `PyDateTime_CAPI` structure obtained via `PyDateTime_IMPORT`. `expect_datetime_api` panics if `ensure_datetime_api` returns `Err` — i.e. importing the `datetime` C API failed (typically because the `datetime` module could not be imported). The panic propagates the fetched `PyErr`'s absence as a Rust panic instead of a Python exception.
Source
Thrown at src/types/datetime.rs:50
#[cfg(not(Py_LIMITED_API))]
use core::ffi::c_int;
#[cfg(not(Py_LIMITED_API))]
fn ensure_datetime_api(py: Python<'_>) -> PyResult<&'static PyDateTime_CAPI> {
if let Some(api) = unsafe { pyo3_ffi::PyDateTimeAPI().as_ref() } {
Ok(api)
} else {
unsafe {
PyDateTime_IMPORT();
pyo3_ffi::PyDateTimeAPI().as_ref()
}
.ok_or_else(|| PyErr::fetch(py))
}
}
#[cfg(not(Py_LIMITED_API))]
fn expect_datetime_api(py: Python<'_>) -> &'static PyDateTime_CAPI {
ensure_datetime_api(py).expect("failed to import `datetime` C API")
}
// Type Check macros
//
// These are bindings around the C API typecheck macros, all of them return
// `1` if True and `0` if False. In all type check macros, the argument (`op`)
// must not be `NULL`. The implementations here all call ensure_datetime_api
// to ensure that the PyDateTimeAPI is initialized before use
//
//
// # Safety
//
// These functions must only be called when the GIL is held!
#[cfg(not(Py_LIMITED_API))]
macro_rules! ffi_fun_with_autoinit {
($(#[$outer:meta] unsafe fn $name: ident($arg: ident: *mut PyObject) -> $ret: ty;)*) => {
$(
#[$outer]View on GitHub (pinned to ac9b6899d3)
Solutions
- Ensure the Python runtime's stdlib (especially `datetime`) is importable: check `sys.path` and that `datetime.py`/`_datetime` module is included in frozen builds
- Add a hidden import of `datetime` in PyInstaller/PyOxidizer configs (`--hidden-import datetime`)
- Verify the interpreter is fully initialized before calling datetime APIs (not during `Py_Finalize`)
- Use `ensure_datetime_api` directly and handle the returned `PyErr` instead of the panicking helper
Example fix
// PyInstaller spec // before # no hidden import, stdlib pruned // after hiddenimports=['datetime']
Defensive patterns
Strategy: validation
Validate before calling
# Python: verify datetime C API availability before calling datetime-dependent Rust code import datetime # raises ImportError early if stdlib is pruned assert hasattr(datetime, 'date')
Type guard
def datetime_api_available() -> bool:
try:
import datetime
return True
except ImportError:
return False Try / catch
try:
result = rust_parse_datetime(value)
except ImportError:
result = fallback_python_parsing(value) Prevention
- Include 'datetime' as a hidden import in PyInstaller/PyOxidizer builds
- Test frozen binaries for stdlib completeness
- Never call datetime-dependent APIs during interpreter finalization
- Keep sys.path pointing at a complete stdlib
When it happens
Trigger: Extracting to `chrono`/`time` datetime types or constructing `PyDateTime`/`PyDate`/`PyTime`/`PyDelta` objects when the `datetime` module is unavailable; frozen/PyOxidizer/PyInstaller builds missing `datetime`; a broken `sys.path` hiding the stdlib.
Common situations: Frozen binaries (PyInstaller, PyOxidizer, embedded Python) that stripped `datetime`; stub-based or partial Python distributions; calling datetime-related Rust APIs at interpreter shutdown.
Related errors
- ignored leap-second, `datetime` does not support leap-second
- Unknown return value from PyDict_SetDefaultRef: {x}
- Neither abi3 or abi3t features are enabled
- Cannot target an abi3t version below {MINIMUM_SUPPORTED_VERS
- failed to run the Python interpreter at {}: {}
AI-assisted analysis of PyO3/pyo3@ac9b6899d3 (2026-09-05).
Data as JSON: /api/errors/9472d2a7a066e767.
Report an issue: GitHub.