Files
rdkit/Code/GraphMol/Wrap/rdmolops.cpp
Yakov Pechersky 872b054d5c Defer numpy initialization to first use (#9127)
* Defer numpy initialization to first use in rdchem, rdmolops, cDataStructs

`from rdkit import Chem` unconditionally bootstrapped numpy (~120ms) via
import_array()/boost::python::numpy::initialize() in module init functions,
even when no numpy-dependent APIs were called. This is costly in cold-start
environments like AWS Lambda.

Move numpy initialization behind lazy guards (static bool + first-call init)
in rdchem.so, rdmolops.so, and cDataStructs.so. Numpy now loads only when
an API that actually needs it is invoked (GetDistanceMatrix, GetPositions,
SetPositions, GetAdjacencyMatrix, ConvertToNumpyArray, etc.).

Also change Conformer::SetPos to accept python::object instead of
np::ndarray to prevent Boost.Python from requiring numpy type conversion
before the lazy guard runs.

Adds test_lazy_numpy.py with subprocess-based tests verifying:
- `from rdkit import Chem` does not load numpy
- SmilesToMol/MolToSmiles work without numpy
- numpy loads on demand when array APIs are called

* skip inchi tests if not available

* switch to threadsafe once_flag, like elsewhere

* finish ifdef style

* switch to magic static style

* Revert "switch to magic static style"

This reverts commit 7300188db7.
2026-02-23 18:42:42 +01:00

56 lines
1.3 KiB
C++

//
// Copyright (C) 2003-2019 Greg Landrum and Rational Discovery LLC
//
// @@ All Rights Reserved @@
// This file is part of the RDKit.
// The contents are covered by the terms of the BSD license
// which is included in the file license.txt, found at the root
// of the RDKit source tree.
//
#include "rdmolops.h"
#include <RDBoost/python.h>
#include <RDGeneral/types.h>
#include <RDBoost/Wrap.h>
#include <RDBoost/import_array.h>
#include <RDGeneral/Exceptions.h>
#include <GraphMol/SanitException.h>
#ifdef RDK_BUILD_THREADSAFE_SSS
#include <mutex>
#endif
namespace python = boost::python;
using namespace RDKit;
#ifdef RDK_BUILD_THREADSAFE_SSS
static std::once_flag s_rdmolops_numpy_init_flag;
#endif
void rdkit_rdmolops_ensure_numpy() {
#ifdef RDK_BUILD_THREADSAFE_SSS
std::call_once(s_rdmolops_numpy_init_flag, rdkit_import_array);
#else
static bool initialized = false;
if (!initialized) {
initialized = true;
rdkit_import_array();
}
#endif
}
void wrap_molops();
void wrap_chiralityops();
BOOST_PYTHON_MODULE(rdmolops) {
python::scope().attr("__doc__") =
"Module containing RDKit functionality for manipulating molecules.";
// ******************************
// Functions from MolOps
//****************************
wrap_molops();
wrap_chiralityops();
}