Prepares the use of Python in a free-threaded context. If the Python interpreter is not already initialized, this function will initialize it with disabled signal handling (Python will not raise the `KeyboardInterrupt` exception). Python signal handling depends on the notion of a 'main thread', which must be the thread that initializes the Python interpreter. If both the Python interpreter and P
()
| 45 | /// will ensure that Python threading is initialized. |
| 46 | /// |
| 47 | pub fn prepare_freethreaded_python() { |
| 48 | // Protect against race conditions when Python is not yet initialized |
| 49 | // and multiple threads concurrently call 'prepare_freethreaded_python()'. |
| 50 | // Note that we do not protect against concurrent initialization of the Python runtime |
| 51 | // by other users of the Python C API. |
| 52 | START.call_once(|| unsafe { |
| 53 | if ffi::Py_IsInitialized() != 0 { |
| 54 | // If Python is already initialized, we expect Python threading to also be initialized, |
| 55 | // as we can't make the existing Python main thread acquire the GIL. |
| 56 | assert!(ffi::PyEval_ThreadsInitialized() != 0); |
| 57 | } else { |
| 58 | #[cfg(feature = "python27-sys")] |
| 59 | { |
| 60 | // If Python isn't initialized yet, we expect that Python threading isn't initialized either. |
| 61 | assert!(ffi::PyEval_ThreadsInitialized() == 0); |
| 62 | // Note: starting with Python 3.2 it's no longer possible to initialize threading |
| 63 | // without initializing Python; and in Python 3.7 PyEval_ThreadsInitialized() started |
| 64 | // misbehaving when Python was not initialized yet. |
| 65 | } |
| 66 | // Initialize Python. |
| 67 | // We use Py_InitializeEx() with initsigs=0 to disable Python signal handling. |
| 68 | // Signal handling depends on the notion of a 'main thread', which doesn't exist in this case. |
| 69 | // Note that the 'main thread' notion in Python isn't documented properly; |
| 70 | // and running Python without one is not officially supported. |
| 71 | ffi::Py_InitializeEx(0); |
| 72 | ffi::PyEval_InitThreads(); |
| 73 | // PyEval_InitThreads() will acquire the GIL, |
| 74 | // but we don't want to hold it at this point |
| 75 | // (it's not acquired in the other code paths) |
| 76 | // So immediately release the GIL: |
| 77 | let _thread_state = ffi::PyEval_SaveThread(); |
| 78 | // Note that the PyThreadState returned by PyEval_SaveThread is also held in TLS by the Python runtime, |
| 79 | // and will be restored by PyGILState_Ensure. |
| 80 | } |
| 81 | }); |
| 82 | } |
| 83 | |
| 84 | /// RAII type that represents the Global Interpreter Lock acquisition. |
| 85 | /// |