Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions newsfragments/5342.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add `Python::try_attach`.
2 changes: 1 addition & 1 deletion pytests/src/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ fn hammer_gil_in_thread() -> LockHolder {
// now the interpreter has shut down, so hammer the GIL. In buggy
// versions of PyO3 this will cause a crash.
loop {
Python::attach(|_py| ());
Python::try_attach(|_py| ());
}
});
LockHolder { sender }
Expand Down
1 change: 0 additions & 1 deletion src/internal/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ impl AttachGuard {
}

/// Variant of the above which will will return `None` if the interpreter cannot be attached to.
#[cfg(any(not(Py_LIMITED_API), Py_3_11, test))] // see Python::try_attach
pub(crate) fn try_acquire() -> Option<Self> {
match ATTACH_COUNT.try_with(|c| c.get()) {
Ok(i) if i > 0 => {
Expand Down
18 changes: 13 additions & 5 deletions src/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,9 @@ impl Python<'_> {
/// - If the [`auto-initialize`] feature is not enabled and the Python interpreter is not
/// initialized.
///
/// To avoid possible initialization or panics if calling in a context where the Python
/// interpreter might be unavailable, consider using [`Python::try_attach`].
///
/// # Examples
///
/// ```
Expand All @@ -419,15 +422,20 @@ impl Python<'_> {
f(guard.python())
}

/// Variant of [`Python::attach`] which will do no work if the interpreter is in a
/// state where it cannot be attached to:
/// Variant of [`Python::attach`] which will return without attaching to the Python
/// interpreter if the interpreter is in a state where it cannot be attached to:
/// - in the middle of GC traversal
/// - not initialized
///
/// Note that due to the nature of the underlying Python APIs used to implement this,
/// the behavior is currently provided on a best-effort basis; it is expected that a
/// future CPython version will introduce APIs which guarantee this behaviour. This
/// function is still recommended for use in the meanwhile as it provides the best
/// possible behaviour and should transparently change to an optimal implementation
/// once such APIs are available.
#[inline]
#[track_caller]
#[cfg(any(not(Py_LIMITED_API), Py_3_11, test))] // only used in buffer.rs for now, allow in test cfg for simplicity
// TODO: make this API public?
pub(crate) fn try_attach<F, R>(f: F) -> Option<R>
pub fn try_attach<F, R>(f: F) -> Option<R>
where
F: for<'py> FnOnce(Python<'py>) -> R,
{
Expand Down
Loading