# PEP 780: ABI features as environment markers

**URL:** <https://discuss.python.org/t/pep-780-abi-features-as-environment-markers/86013>\
**Category:** Standards\
**Created:** [March 26, 2025, 10:34am UTC](https://discuss.python.org/t/pep-780-abi-features-as-environment-markers/86013 "2025-03-26T10:34:40Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![zklaus](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/zklaus/32/25923_2.png) [@zklaus](https://discuss.python.org/u/zklaus)\
**Post date:** [March 26, 2025, 10:34am UTC](https://discuss.python.org/t/pep-780-abi-features-as-environment-markers/86013/1 "2025-03-26T10:34:40Z")

</div>

Hi!

We are excited to present [PEP 780—ABI features as environment markers](https://peps.python.org/pep-0780/). We believe there is a need to make ABI features like free-threading available as environment markers for dependency specification and beyond that to improve accessibility of ABI features.

This PEP is strongly influenced by [an earlier discussion](https://discuss.python.org/t/60007).

We look forward to everyone’s feedback and interesting discussions!

## Abstract

This PEP defines using ABI features as environment markers for project dependencies, through a new `sys_abi_features` environment marker and `sys.abi_features` attribute in the `sys` module.  
[PEP 508](https://peps.python.org/pep-0508/) (later moved to [the Python Packaging User Guide](https://packaging.python.org/en/latest/specifications/dependency-specifiers/#dependency-specifiers)) introduced environment markers to specify dependencies based on rules that describe when the dependency should be used.

This PEP extends the environment markers to allow specifying dependencies based on specific ABI features of the Python interpreter. For this, it defines a set of ABI features and specifies how they are made available via an addition to the Python Standard Library in the form of a new attribute `sys.abi_features`, as well as for environment markers as a new marker variable,  
`sys_abi_features`.

An example of use in dependency specification is

```python
cython >3.1.0a1; "free-threading" in sys_abi_features
cython ==3.0.*; "free-threading" not in sys_abi_features

```

More examples can be found in the document.

## PEP

> **[PEP 780 – ABI features as environment markers | peps.python.org](https://peps.python.org/pep-0780/)**
>
> This PEP defines using ABI features as environment markers for project dependencies, through a new sys\_abi\_features environment marker. PEP 508 (later moved to packaging:dependency-specifiers) introduced environment markers to specify dependencies...

---

<div class="post-metadata">

**Author:** ![XuehaiPan](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/xuehaipan/32/9029_2.png) [@XuehaiPan](https://discuss.python.org/u/XuehaiPan)\
**Post date:** [March 26, 2025, 11:07am UTC](https://discuss.python.org/t/pep-780-abi-features-as-environment-markers/86013/2 "2025-03-26T11:07:44Z")

</div>

> [@zklaus](#):
>
> This PEP extends the environment markers to allow specifying dependencies based on specific ABI features of the Python interpreter.

Is there any specification for the `sys.abi_features` attribute to be a static compile-time constant or dynamically runtime-dependent?

For the former, some [feature names](https://peps.python.org/pep-0780/#abi-features) can be ambiguous (e.g., `gil-enabled`). On free-threading build, the GIL can still be controlled by `-X gil=0/1` and `PYTHON_GIL=0/1`.

```python
# static
Py_GIL_DISABLED = bool(sysconfig.get_config_var("Py_GIL_DISABLED"))

# runtime dependent
gil_disabled = not sys._is_gil_enabled()

```

The latter one needs to implement a `sys. __getattr__ ` function (see [gh-127405: Emit a deprecation warning about a future change of `sys.abiflags` availability on Windows by XuehaiPan · Pull Request #131717 · python/cpython · GitHub](https://github.com/python/cpython/pull/131717)). I can imagine a potential breakage while users install and run the package with a different `PYTHON_GIL` environment.

---

<div class="post-metadata">

**Author:** ![pf\_moore](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/pf_moore/32/35_2.png) [@pf\_moore](https://discuss.python.org/u/pf_moore)\
**Post date:** [March 26, 2025, 11:17am UTC](https://discuss.python.org/t/pep-780-abi-features-as-environment-markers/86013/3 "2025-03-26T11:17:22Z")

</div>

> [@XuehaiPan](#):
>
> Is there any specification for the `sys.abi_features` attribute to be a static compile-time constant or dynamically runtime-dependent?

To be usable as a marker, the values in `sys.abi_features` would have to be static, defined by the Python interpreter. Markers are used to decide what code to install in an environment, and if running the interpreter with a different flag, or changing a setting in a running interpreter, makes the code installed invalid, that’s incompatible with the expectations people have of markers.

The point about re-enabling/disabling the GIL at runtime is an important one. What would

```python
python -X gil=0 -m pip install some_pkg

```

do if run on a free-threaded implementation of Python, if `some_pkg` depends on `thread_utils; "free-threading" in sys_abi_features"`? Would it install `thread_utils`?

```python
python -X gil=1 -c "import some_pkg"

```

work after such an install command? Or would it fail because `thread_utils` wasn’t installed?

---

<div class="post-metadata">

**Author:** ![oscarbenjamin](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/oscarbenjamin/32/1209_2.png) [@oscarbenjamin](https://discuss.python.org/u/oscarbenjamin)\
**Post date:** [March 26, 2025, 11:38am UTC](https://discuss.python.org/t/pep-780-abi-features-as-environment-markers/86013/4 "2025-03-26T11:38:25Z")

</div>

> [@pf\_moore](#):
>
> The point about re-enabling/disabling the GIL at runtime is an important one. What would
> 
> ```python
> python -X gil=0 -m pip install some_pkg
> 
> ```
> 
> do if run on a free-threaded implementation of Python

It would do exactly the same as without the `gil=0` flag:

```python
python -m pip install some_pkg

```

This is needed for precisely the reason you stated: the installed package needs to be compatible with all the ways that Python might be run in this particular environment. It is the package authors job to make sure that the version of their package that is installed under freethreading would be compatible with gil=0 and/or gil=1 (if they want to support that) or whether any extension modules re-enable the GIL etc.

---

<div class="post-metadata">

**Author:** ![rgommers](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/rgommers/32/837_2.png) [@rgommers](https://discuss.python.org/u/rgommers)\
**Post date:** [March 26, 2025, 12:16pm UTC](https://discuss.python.org/t/pep-780-abi-features-as-environment-markers/86013/5 "2025-03-26T12:16:26Z")

</div>

> [@pf\_moore](#):
>
> To be usable as a marker, the values in `sys.abi_features` would have to be static, defined by the Python interpreter.

Yes, this indeed. The ABI is static, and won’t be affected by a user passing `-X gil` or not. Since it’s apparently not 100% clear, we’ll make sure to state this very explicitly in the next update to the PEP.

---

<div class="post-metadata">

**Author:** ![rgommers](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/rgommers/32/837_2.png) [@rgommers](https://discuss.python.org/u/rgommers)\
**Post date:** [March 26, 2025, 12:18pm UTC](https://discuss.python.org/t/pep-780-abi-features-as-environment-markers/86013/6 "2025-03-26T12:18:43Z")

</div>

I think this post should have had `Packaging` and `Standards` tags, rather than `PEPs`. Can it still be moved by a moderator?

---

<div class="post-metadata">

**Author:** ![steve.dower](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/steve.dower/32/56_2.png) [@steve.dower](https://discuss.python.org/u/steve.dower)\
**Post date:** [March 26, 2025, 1:13pm UTC](https://discuss.python.org/t/pep-780-abi-features-as-environment-markers/86013/7 "2025-03-26T13:13:31Z")

</div>

> [@rgommers](#):
>
> I think this post should have had `Packaging` and `Standards` tags, rather than `PEPs`.

The PEP contains a section “Adding `sys.abi_features` to the Python Standard Library”, which requires a core PEP.

You may need to split into two PEPs to enable the packaging side of it. Though it’s possible that a PEP could be skipped if it’s literally just going to be to enable `x in sys_abi_features` on versions of the runtime where the `sys` attribute exists.

(And just to be 100% clear, I think the post was and the PEP is correctly classified, it just has to talk less about environment markers as _specification_ and move them to examples of how the new `sys.abi_features` attribute might be used.)

---

<div class="post-metadata">

**Author:** ![rgommers](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/rgommers/32/837_2.png) [@rgommers](https://discuss.python.org/u/rgommers)\
**Post date:** [March 26, 2025, 1:27pm UTC](https://discuss.python.org/t/pep-780-abi-features-as-environment-markers/86013/8 "2025-03-26T13:27:40Z")

</div>

> [@steve.dower](#):
>
> The PEP contains a section “Adding `sys.abi_features` to the Python Standard Library”, which requires a core PEP.

This was discussed on [https://github.com/python/peps/pull/4315#discussion\_r2007997314](https://github.com/python/peps/pull/4315#discussion_r2007997314), with the reviewers agreeing it was too minor. Do you really want to require a full separate PEP just for adding `sys.abi_features`?

---

<div class="post-metadata">

**Author:** ![steve.dower](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/steve.dower/32/56_2.png) [@steve.dower](https://discuss.python.org/u/steve.dower)\
**Post date:** [March 26, 2025, 3:46pm UTC](https://discuss.python.org/t/pep-780-abi-features-as-environment-markers/86013/10 "2025-03-26T15:46:39Z")

</div>

> [@rgommers](#):
>
> agreeing it was too minor

I haven’t seen many cases of “arbitrary sets of words we expect everyone to agree on the meaning of” be deemed too minor. That’s not to say that the full list of names for all time needs to be fixed by the PEP, but at least the definition, naming conventions, deprecation process, addition process, and overall rationale ought to be clearly spelled out for future reference (and our format for that is a PEP).

[PEP 421](https://peps.python.org/pep-0421/) (adding `sys.implementation`) is a good reference. It might even be the right place for adding `abi_features`…?

I also suggested [on a semi-related PR](https://github.com/python/cpython/pull/131717#issuecomment-2752735902) that a PEP introducing `abi_features` could also deprecate `sys.abiflags`, which ought to be adequately covered by `sysconfig` (for cases where you really just want the exact flags and not the list of features) and has cross-platform complications right now meaning it isn’t a good alternative for the proposed `abi_features` but could distract from it.

But the main point is that the discussion of this feature is already fragmented, and running it through the normal PEP process will bring it together (or at least formally exclude discussion that doesn’t revolve around the PEP).

Once it exists, I would expect that making it available as a marker is the part that becomes too minor to need a PEP.

---

<div class="post-metadata">

**Author:** ![pf\_moore](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/pf_moore/32/35_2.png) [@pf\_moore](https://discuss.python.org/u/pf_moore)\
**Post date:** [March 26, 2025, 4:06pm UTC](https://discuss.python.org/t/pep-780-abi-features-as-environment-markers/86013/11 "2025-03-26T16:06:58Z")

</div>

> [@steve.dower](#):
>
> Once it exists, I would expect that making it available as a marker is the part that becomes too minor to need a PEP.

lol, I can’t help but find this ironic. You think the packaging community is more likely to be able to agree that something is minor and can just be added without a discussion than the core developers?

I’d hope it would be a small and pretty uncontroversial PEP. I’d even be willing to consider a proposal to add it just as a textual change to the relevant standard\[1\]. But I doubt that would get consensus, and the debate could easily be more effort than just writing a PEP would be.

* * *

1. although we’ve had bad experiences with “obviously uncontroversial” changes made without a PEP in the past

---

<div class="post-metadata">

**Author:** ![steve.dower](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/steve.dower/32/56_2.png) [@steve.dower](https://discuss.python.org/u/steve.dower)\
**Post date:** [March 26, 2025, 5:46pm UTC](https://discuss.python.org/t/pep-780-abi-features-as-environment-markers/86013/12 "2025-03-26T17:46:33Z")

</div>

> [@pf\_moore](#):
>
> lol, I can’t help but find this ironic. You think the packaging community is more likely to be able to agree that something is minor and can just be added without a discussion than the core developers?

Of course I don’t think that 😃 But since there’s [already a PEP](https://peps.python.org/pep-0508/) and [a specification](https://packaging.python.org/en/latest/specifications/dependency-specifiers/#environment-markers) with a list of markers, I’d hope that adding a new marker that’s been thoroughly defined by someone else would only require a spec update and not an entirely new motivation.

Though the “Unknown variables must raise an error” part of that spec may cause issues when adding a variable that isn’t available on earlier versions but could be reasonably inferred…

---

<div class="post-metadata">

**Author:** ![zklaus](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/zklaus/32/25923_2.png) [@zklaus](https://discuss.python.org/u/zklaus)\
**Post date:** [April 14, 2025, 5:33pm UTC](https://discuss.python.org/t/pep-780-abi-features-as-environment-markers/86013/13 "2025-04-14T17:33:57Z")

</div>

It seems a lot of discussion focuses around whether this is more of core PEP or more of a packaging PEP. As we definitely intent to discuss this as a packaging PEP first, we will remove the CPython aspects from the PEP to disentangle things a bit better and focus on discussing the remaining environment marker and packaging aspects here.

The CPython changes can be discussed separately, perhaps as a simple PR with core agreement, or, if that proves unexpectedly necessary, as a separate PEP.

---

<div class="post-metadata">

**Author:** ![zklaus](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/zklaus/32/25923_2.png) [@zklaus](https://discuss.python.org/u/zklaus)\
**Post date:** [April 18, 2025, 6:54pm UTC](https://discuss.python.org/t/pep-780-abi-features-as-environment-markers/86013/14 "2025-04-18T18:54:59Z")

</div>

We have now updated the PEP to completely focus on the environment marker with no mention of the initially proposed standard library addition.

It would be great to hear everybody’s thoughts on these packaging related aspects, such as if the naming of the features is appropriate and whether any crucial ABI aspects have been overlooked?

---

<div class="post-metadata">

**Author:** ![steve.dower](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/steve.dower/32/56_2.png) [@steve.dower](https://discuss.python.org/u/steve.dower)\
**Post date:** [April 21, 2025, 2:10pm UTC](https://discuss.python.org/t/pep-780-abi-features-as-environment-markers/86013/15 "2025-04-21T14:10:21Z")

</div>

> [@zklaus](#):
>
> We have now updated the PEP to completely focus on the environment marker with no mention of the initially proposed standard library addition.

Is there a separate proposal to add the `sys.abi_features` member?

If not, then my feedback here is that we shouldn’t add something that looks like part of the `sys` module when it isn’t part of the `sys` module. (My preference is to add it to `sys` first and then enable it for environment markers - libraries can backfill the value pre-3.14/3.15.)

---

<div class="post-metadata">

**Author:** ![zklaus](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/zklaus/32/25923_2.png) [@zklaus](https://discuss.python.org/u/zklaus)\
**Post date:** [April 29, 2025, 10:24am UTC](https://discuss.python.org/t/pep-780-abi-features-as-environment-markers/86013/16 "2025-04-29T10:24:11Z")

</div>

> Is there a separate proposal to add the `sys.abi_features` member?

Yes, I have created an [issue](https://github.com/python/cpython/issues/133143) in the CPython repo. I hope we can get consensus there.

---

<div class="post-metadata">

**Author:** ![mgorny](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/mgorny/32/34029_2.png) [@mgorny](https://discuss.python.org/u/mgorny)\
**Post date:** [May 26, 2025, 2:11pm UTC](https://discuss.python.org/t/pep-780-abi-features-as-environment-markers/86013/17 "2025-05-26T14:11:22Z")

</div>

Few notes:

1. I don’t think there’s technically a need to have a 1:1 `sys.abi_features` — but I’m not opposed to having it either.
2. In either case, the specification should probably include the “Python equivalents” for every feature — i.e. “how do you check if the marker should be present?” In particular, the split between “32-bit” and “64-bit” builds is pretty ambiguous to me (is MIPS n32 ABI a “32-bit” or “64-bit” build?).
3. I don’t really understand the need for both `free-threading` and `gil-enabled` markers. Given that we have both `in` and `not in` operators, I think a single feature would suffice. Having two makes me wonder if there’s a corner case I didn’t think of.

---

<div class="post-metadata">

**Author:** ![zklaus](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/zklaus/32/25923_2.png) [@zklaus](https://discuss.python.org/u/zklaus)\
**Post date:** [June 4, 2025, 4:40pm UTC](https://discuss.python.org/t/pep-780-abi-features-as-environment-markers/86013/18 "2025-06-04T16:40:37Z")

</div>

Thanks for your notes, @mgorny!

1. Sounds good. We’ll take the discussion about that feature in [Add `sys.abi_features` to make information about the interpreter ABI more accessible](https://discuss.python.org/t/94422) and [Add `sys.abi_features` to make information about the interpreter ABI more accessible · Issue #133143 · python/cpython · GitHub](https://github.com/python/cpython/issues/133143).
2. The [intended reference implementation](https://github.com/zklaus/cpython/pull/1) determines the bitness by looking at the `PY_SSIZE_T_MAX` constant, though it was suggested to use `SIZEOF_VOID_P` instead. Either way, you get the idea: we try to understand what is the pointer width. This is useful to know for example on Windows, where Scipy is not available for the widely used 32-bit variant due to lack of a suitable Fortran compiler toolchain.
3. You are right that strictly speaking at the moment not both are needed. It comes down to better expressiveness (are you interested in a feature that should generally work, except for one of the two something goes wrong? or are you rather explicitly targeting one of the two?) and possible future extensions with a third option (e.g. `sub-interpreters`).

---

<div class="post-metadata">

**Author:** ![zklaus](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/zklaus/32/25923_2.png) [@zklaus](https://discuss.python.org/u/zklaus)\
**Post date:** [September 18, 2025, 3:47pm UTC](https://discuss.python.org/t/pep-780-abi-features-as-environment-markers/86013/19 "2025-09-18T15:47:49Z")

</div>

[https://github.com/python/cpython/pull/137476](https://github.com/python/cpython/pull/137476) was merged and Python will have a new `sys` attribute 🎉. However, the discussion led to a few modifications, so instead of `sys.abi_features` as a frozen set, we now have a namespace `sys.abi_info` with four fields as follows

> `abi_info.pointer_bits`  
> The width of pointers in bits, as an integer, equivalent to `8 * sizeof(void *)`. Usually, this is `32 `or `64`.
> 
> `abi_info.free_threaded`  
> A Boolean indicating whether the interpreter was built with free threading support. This reflects either the presence of the `--disable-gil` `configure` option (on Unix) or setting the `DisableGil` property (on Windows).
> 
> abi\_info.debug  
> A Boolean indicating whether the interpreter was built in debug mode. This reflects either the presence of the `--with-pydebug` `configure` option (on Unix) or the `Debug` configuration (on Windows).
> 
> `abi_info.byteorder`  
> A string indicating the native byte order, either ‘big’ or ‘little’. This is the same as the `sys.byteorder` attribute.

This requires a slight modification of the syntax, as we now need to take values for the different fields into account. We propose `"{field}::{value}" in sys_abi_info`, for example `"pointer_bits::64" in sys_abi_info`. Note that quoting of the string remains necessary; for convenience, we suggest to allow for whitespace around the `::` separator.

I think it’s best to require `{value}` even for booleans, for example `"free_threaded::true" in sys_abi_info`.

I’ll adapt the reference implementation and the PEP accordingly.

What do you think?

---

<div class="post-metadata">

**Author:** ![zklaus](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/zklaus/32/25923_2.png) [@zklaus](https://discuss.python.org/u/zklaus)\
**Post date:** [September 22, 2025, 4:36pm UTC](https://discuss.python.org/t/pep-780-abi-features-as-environment-markers/86013/20 "2025-09-22T16:36:56Z")

</div>

The updated reference implementation is now [available](https://github.com/zklaus/packaging/pull/1).

---

<div class="post-metadata">

**Author:** ![pradyunsg](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/pradyunsg/32/206_2.png) [@pradyunsg](https://discuss.python.org/u/pradyunsg)\
**Post date:** [September 22, 2025, 5:47pm UTC](https://discuss.python.org/t/pep-780-abi-features-as-environment-markers/86013/21 "2025-09-22T17:47:26Z")

</div>

Could you also update the PEP text, to reflect the current proposal?

[Next page](https://discuss.python.org/t/pep-780-abi-features-as-environment-markers/86013.md?page=2)
