Skip to content

Add sys._is_gil_enabled() #117514

Closed
Closed

Description

@colesbury

Feature or enhancement

I propose adding a new function to the sys module to check if the GIL is current enabled:

sys._is_gil_enabled() -> bool

Return True if the GIL is currently enabled and False if the GIL is currently disabled.

The function would always return True in builds that do not support free-threading. In the free-threaded build, the the GIL might be dynamically enabled or disabled depending on imported modules.

EDIT: Changed name to use underscore prefix

Linked PRs

Activity

  1. zooba commented on Apr 3, 2024

    @zooba
    Member

    What do you expect developers to do with this value? Is it merely for reporting details about bugs? Or is there some programmatic reason you may want to know this?

  2. gpshead commented on Apr 3, 2024

    @gpshead
    Member

    I'd expect likely just reporting. Similar to things like sys.is_stack_trampoline_active(). It isn't an API likely to be logically useful to most code. But the reporting aspect is important, especially for test runners.

  3. colesbury commented on Apr 3, 2024

    @colesbury
    ContributorAuthor

    I think the diagnostic and bug reporting uses are most straight-forward: is the GIL really disabled? Especially because it looks like we will be temporarily enabling the GIL around imports.

    I think it might also be useful in a few cases for choosing reasonable defaults: i.e., does a thread-pool or multiprocessing backend make more sense as a default in some library (like PyTorch data loaders or joblib).

  4. zooba commented on Apr 3, 2024

    @zooba
    Member

    I fear it won't be particularly useful for either of those cases with the current proposed (temporary?) semantics.

    Reporting feels like it ought to be "was the GIL enabled when X went wrong", while selecting defaults feels like "will the GIL be enabled under normal operation".

    Otherwise the semantics of "don't call this during import" are going to be very unhelpful, both to explain and to reveal internal behaviour details and require users to design around them.

    How about a CPython-specific sys._is_gil_enabled() to return the status right now, and a more generic sys.is_free_threaded() (that could also be implemented in other runtimes) to return the intent of the runtime?

    (FWIW, I'd have argued is_stack_trampoline_active() should have an underscore, like sys._getframe() and sys._git, but I missed that proposal.)

  5. colesbury commented on Apr 3, 2024

    @colesbury
    ContributorAuthor

    That seems like a more confusing API to me. I don't think there's a sufficient need for sys.is_free_threaded() and "intent of the runtime" strikes me as too vague of a concept to be useful. We already have other mechanisms for querying the build configuration and runtime initialization flags.

    What do you mean by "don't call this during import"?

  6. colesbury commented on Apr 3, 2024

    @colesbury
    ContributorAuthor

    We are only planning to do the temporary GIL enabling around imports of C-API extensions, not Python modules so I don't think there's any reason not to call sys.is_gil_enabled() during an import. I don't think users have to design around it.

  7. zooba commented on Apr 3, 2024

    @zooba
    Member

    We already have other mechanisms for querying the build configuration and runtime initialization flags.

    Mechanisms that don't exist in, say, IronPython, which is nonetheless free threaded, and given the choice between threads or processes you would likely choose threads for similar kinds of tasks that you would under free-threaded CPython.

    The sys module is supposed to be consistent across implementations, so it's worth considering how other implementations will explain and handle the function.

  8. colesbury commented on Apr 3, 2024

    @colesbury
    ContributorAuthor

    The sys module is supposed to be consistent across implementations, so it's worth considering how other implementations will explain and handle the function.

    I agree, and I think that sys.is_gil_enabled() is straight-forward to use and explain: if implemented in IronPython it can always return False. If implemented in PyPy, it can always return True.

  9. zooba commented on Apr 3, 2024

    @zooba
    Member

    It just feels a bit weird to suddenly introduce "GIL" as a Python-wide concept when previously it was only ever a CPython implementation detail (a public one, to be sure, but not a cross-implementation concern in any way). Especially since the plan is to eventually have everyone return False all the time.

    Why is it so bad to make it a documented underscored function _is_gil_enabled? (And thereby not require other implementations to worry about it.)

  10. colesbury commented on Apr 3, 2024

    @colesbury
    ContributorAuthor

    I prefer sys.is_gil_enabled, but I don't think having only the underscored sys._is_gil_enabled() is so bad.

    It's more the combination of sys._is_gil_enabled() and sys.is_free_threaded that I think is confusing.

  11. gpshead commented on Apr 3, 2024

    @gpshead
    Member

    It's also fair to just start with the _is_gil_enabled() name so that we can change this later. (feel free to document that _ API, just mention that its existence or name may change in future minor python versions so people who want to use it should check for it). We can base a future decision to make a non _ name based on what we find users actually found a need for.

  12. changed the title [-]Add `sys.is_gil_enabled()`[/-] [+]Add `sys._is_gil_enabled()`[/+] on Apr 3, 2024
  13. colesbury commented on Apr 3, 2024

    @colesbury
    ContributorAuthor

    I've updated the issue to sys._is_gil_enabled().

  14. tonybaloney commented on Apr 23, 2024

    @tonybaloney
    Contributor

    I came here to ask for this feature, I needed it to determine which execution model would work best (multiprocessing or thread pools) at runtime and the python -m sysconfig output only told me the compile-time value.

    In answer to the "why would anyone need this", I'd just spent an hour looking for this flag :-)

  15. zooba commented on Apr 24, 2024

    @zooba
    Member

    In answer to the "why would anyone need this", I'd just spent an hour looking for this flag :-)

    I was aware of this scenario, which is why I suggested is_free_threaded as a generic alternative to answer "should I use subprocesses or threads" without necessarily exposing implementation details.

  16. added 3 commits that reference this issue on May 2, 2024
  17. added a commit that references this issue on May 8, 2024
  18. devinrsmith commented on Jan 12, 2026

    @devinrsmith

    Is there a C API stable way of checking this?

  19. colesbury commented on Jan 12, 2026

    @colesbury
    ContributorAuthor

    There's no dedicated C API function. You can call Python functions from C. Something like:

    int
    is_gil_enabled(void)
    {
        PyObject *sys_mod = NULL;
        PyObject *func = NULL;
        PyObject *res = NULL;
        int ret = -1;
    
        sys_mod = PyImport_ImportModule("sys");
        if (sys_mod == NULL) {
            return -1;
        }
    
        func = PyObject_GetAttrString(sys_mod, "_is_gil_enabled");
        if (func == NULL) {
            if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
                PyErr_Clear();
                ret = 1;
            }
            goto done;
        }
    
        if (!PyCallable_Check(func)) {
            ret = 1;
            goto done;
        }
    
        res = PyObject_CallNoArgs(func);
        if (res == NULL) {
            ret = -1;
            goto done;
        }
    
        ret = PyObject_IsTrue(res);
    
    done:
        Py_XDECREF(res);
        Py_XDECREF(func);
        Py_DECREF(sys_mod);
        return ret;
    }
  20. devinrsmith commented on Jan 12, 2026

    @devinrsmith

    Thanks for the confirmation, this is what I was able to determine as well; filed #143747 as a feature request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions