# Mismatch between assert's semantics and how it's used (-O, -OO, disable)

**URL:** <https://discuss.python.org/t/mismatch-between-asserts-semantics-and-how-its-used-o-oo-disable/29282>\
**Category:** Ideas\
**Created:** [July 8, 2023, 9:14pm UTC](https://discuss.python.org/t/mismatch-between-asserts-semantics-and-how-its-used-o-oo-disable/29282 "2023-07-08T21:14:48Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![SonOfLilit](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/sonoflilit/32/13312_2.png) [@SonOfLilit](https://discuss.python.org/u/SonOfLilit)\
**Post date:** [July 8, 2023, 9:14pm UTC](https://discuss.python.org/t/mismatch-between-asserts-semantics-and-how-its-used-o-oo-disable/29282/1 "2023-07-08T21:14:48Z")

</div>

TL;DR Python’s `assert` statement in a NOP [in optimized mode](https://docs.python.org/3/using/cmdline.html#cmdoption-O) (`python -O` or `python -OO`). There exists code that assumes this, and much much more code that is ignorant of this and broken when running with `-O`. Lets do something about this, trying not to break existing code.

This was [discussed](https://discuss.python.org/t/stop-ignoring-asserts-when-running-in-optimized-mode/13132/67) here before at length without getting anywhere, so I’ll try to make a summary of the discussion and then offer some thoughts and a few ways forward.

- `-O` strips `assert`s and defines ` __debug__ ` as `False` (and `if False: stuff` is always stripped by the compiler), `-OO` also strips docstrings
- Guido is against changing the language, prefers to deprecate `-O` and `-OO`
- This gotcha is featured in lists of python security pitfalls
- The fact that it’s often not the same people who write the code and who run it (especially in the case of dependencies) makes it hard to push the idea that “it’s alright because you can always choose not to use `-O`”, and this alone steers people to use neither `-O` nor assert.
- There is at least one library (`click`) that relies on assertion stripping to run slow checks in performance-critical sections
- There are multiple volunteers to write a PEP if a core dev would sponsor it

> **More things that were discussed**
>
> - Python’s `assert` was modeled after C’s `assert()` macro, which is stripped by `-DNDEBUG` (which is a separate argument than `-O`)
> - Traditionally it was stripped from release builds [Editor’s Note: however, these days, at least commercial C/C++ projects tend to keep assertions in release, to the point that I consider it a best practice. `CPython` strips them)
> - The idea comes from Eiffel, where they serve a very specific purpose and have very specific semantics [EN: and some of them are kept in release by default and others stripped]
> 
> - Theoretically, if someone writes an assert that depends on user input and not just on the programmer not being wrong, they’re “using it wrong”
> - In practice…
> - Many have a dislike for code behaving differently in test and production, as it creates hard to debug issues
> - Some people think `AssertionError` should have been a `BaseException` and any code that handles it is suspicious, because if programmer assumptions have been broken, any bad thing might happen. In practice, web servers catch it and log an error and it’s probably wise
> 
> - The non-stripped assertion behavior can’t be easily replicated with a function, because `assert` only evaluates the second parameter if the assertion fails and functions always evaluate all arguments, also because an assert is very self-documenting in a traceback (when the bottom line of a traceback is `assert author is not None`, there’s no need for a message “author is None”)
> - Rust has `assert!` and `debug_assert!`
> - Surprisingly, `pytest` assertions are _not_ stripped with `-O` because of their AST magic

I think @Tinche said it best:

> As a person in charge of operating a large-scale Python deployment, am I expected to run with -O in production or not? If the answer is ‘yes’, I’ve been doing it wrong for a large number of years and we absolutely need to communicate this better, and it complicates the deployment story further. If the answer is ‘no’, asserts should always work.

My own novel thoughts:

`assert` is my favorite python statement, and in 15 years of python the only place I’ve encountered `-O` until today was in github issues asking to replace it with the cumbersome `if not condition: raise AssertionError(msg)`

Maybe if assertions are not “used wrong” we don’t _need_ to run them in production, but I’ve yet to meet a CTO that would prefer the perf gains to the loud crashing behavior when the impossible does happen. This is Python, not C, if we cared about the performance tax of one more statement and a few variable lookups and attribute lookups, we’d be writing that function in Rust or something. Assertions that call a costly function are _very_ rare.

However, assertions that are “using it wrong” are very common, which means `-O` is completely broken and anyone using it does it at their own risk. `stdlib` is full of assertions that check for things determined by the non-stdlib caller, which means they’re broken in `-O`. See e.g. the `Threading` module, GH-106236.

There are rare cases where we do care about them being optimized out in production, so may I propose that we add new syntax for that… how about:

```python
assert not __debug__ or condition, message

```

(Joking, this is not new syntax, it’s an idiom that achieves exactly the same behavior and is more explicit about it)

So my proposal is:

1. Deprecate `-O` and `-OO`, replace with `-O=1` and `-O=2` that don’t strip `assert`s
2. Recommend `assert not __debug__ or condition, message` as an alternative in the deprecation message and in the docs (so if you google ` __debug__ ` the first result will be an explanation of the idiom)

I volunteer to personally pore over the standard library and fix all uses where performance matters, though I couldn’t find any in a preliminary search. And also over `click` and any other open source library who’s maintainer chimes in that they care about this.

So we have a deprecation that fixes many bugs in the `stdlib` and in user code and requires (only) affected users to change how they call `python` to indicate they’re aware of the change, an explicit way to opt-in to the surprising behavior that already works, and even if someone misses the deprecation, in theory the only change they’ll experience is a performance regression, and in practice they might also get their bacon saved by an explicit crash instead of silent misbehavior in production.

Will someone sponsor this?

---

<div class="post-metadata">

**Author:** ![MRAB](https://avatars.discourse-cdn.com/v4/letter/m/e9c0ed/32.png) [@MRAB](https://discuss.python.org/u/MRAB)\
**Post date:** [July 8, 2023, 11:03pm UTC](https://discuss.python.org/t/mismatch-between-asserts-semantics-and-how-its-used-o-oo-disable/29282/2 "2023-07-08T23:03:59Z")

</div>

If most people don’t use `-OO`, and if a language change were acceptable, how about prefixing with `try`, i.e. `try assert <condition>, <message>`, the implication being that it’s tried only if you’re debugging?

---

<div class="post-metadata">

**Author:** ![Rosuav](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/rosuav/32/3429_2.png) [@Rosuav](https://discuss.python.org/u/Rosuav)\
**Post date:** [July 8, 2023, 11:19pm UTC](https://discuss.python.org/t/mismatch-between-asserts-semantics-and-how-its-used-o-oo-disable/29282/3 "2023-07-08T23:19:26Z")

</div>

What about keeping assert’s semantics the same, but having a new `ensure` (which might only be a builtin, not a keyword), which has the semantics people expect of assert? I don’t like the idea that identical code will have subtly different behaviour on different versions, but perhaps it’s sufficient to tell people “hey, if you’ve been using `assert` like this, you probably should switch to `ensure` instead”.

---

<div class="post-metadata">

**Author:** ![SonOfLilit](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/sonoflilit/32/13312_2.png) [@SonOfLilit](https://discuss.python.org/u/SonOfLilit)\
**Post date:** [July 8, 2023, 11:48pm UTC](https://discuss.python.org/t/mismatch-between-asserts-semantics-and-how-its-used-o-oo-disable/29282/4 "2023-07-08T23:48:05Z")

</div>

> [@MRAB](#):
>
> if a language change were acceptable

Why do a language change with all the involved pain when we can achieve exactly the same result with existing constructs? `assert __debug__ and condition, message` does exactly what we want.

> [@Rosuav](#):
>
> What about keeping assert’s semantics the same, but having a new `ensure` (which might only be a builtin, not a keyword), which has the semantics people expect of assert

This has the disadvantage of not doing anything about the huge amounts of code that is out there, much of it _in the python standard library_, that “uses assertions wrong”.

---

<div class="post-metadata">

**Author:** ![Rosuav](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/rosuav/32/3429_2.png) [@Rosuav](https://discuss.python.org/u/Rosuav)\
**Post date:** [July 9, 2023, 12:00am UTC](https://discuss.python.org/t/mismatch-between-asserts-semantics-and-how-its-used-o-oo-disable/29282/5 "2023-07-09T00:00:50Z")

</div>

> [@SonOfLilit](#):
>
> > [@Rosuav](#):
> >
> > What about keeping assert’s semantics the same, but having a new `ensure` (which might only be a builtin, not a keyword), which has the semantics people expect of assert
> 
> This has the disadvantage of not doing anything about the huge amounts of code that is out there, much of it _in the python standard library_, that “uses assertions wrong”.

True, but even if you do “do something” about that code, it will continue to be wrong on existing Python versions, AND it will have the perceived blessing of now being “correct code”. That means that code will be sanctioned as “good code” while being subtly wrong, which IMO is worse than the status quo of it being subtly wrong but acknowledged as bad code.

---

<div class="post-metadata">

**Author:** ![SonOfLilit](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/sonoflilit/32/13312_2.png) [@SonOfLilit](https://discuss.python.org/u/SonOfLilit)\
**Post date:** [July 9, 2023, 12:07am UTC](https://discuss.python.org/t/mismatch-between-asserts-semantics-and-how-its-used-o-oo-disable/29282/6 "2023-07-09T00:07:12Z")

</div>

I don’t see why? Anyone could still go and fix it for existing versions on a case by case basis by replacing `assert x, m` with either `assert not __debug__ or x, m` or `if not x: raise AssertionError(m)`. This fix is even forward-compatible. I just don’t see anyone actually doing it, and an `ensure` builtin won’t improve the situation.

So `-O` remains unusable in practice on existing versions, just like it is right now, but at least its replacement `-O1` becomes usable in the next version (and more importantly, `assert` becomes usable, and existing subtly-wrong uses are retconned to be correct).

---

<div class="post-metadata">

**Author:** ![Rosuav](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/rosuav/32/3429_2.png) [@Rosuav](https://discuss.python.org/u/Rosuav)\
**Post date:** [July 9, 2023, 12:18am UTC](https://discuss.python.org/t/mismatch-between-asserts-semantics-and-how-its-used-o-oo-disable/29282/7 "2023-07-09T00:18:16Z")

</div>

> [@SonOfLilit](#):
>
> I don’t see why? Anyone could still go and fix it for existing versions on a case by case basis by replacing `assert x, m` with either `assert __debug__ and x, m` or `if not x: raise AssertionError(m)`. This fix is even forward-compatible. I just don’t see anyone actually doing it, and an `ensure` builtin won’t improve the situation.

The reason they won’t do it is because there’s no need to - if the code is correct, why change it? But if the code is wrong and there’s an easy solution (“use ensure instead of assert”), there is a stronger incentive to change it.

But maybe I’m the wrong person to be discussing this, since I have never used assert for anything that I wouldn’t have been willing to write as a comment.

---

<div class="post-metadata">

**Author:** ![jrivers](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/jrivers/32/12134_2.png) [@jrivers](https://discuss.python.org/u/jrivers)\
**Post date:** [July 9, 2023, 2:32am UTC](https://discuss.python.org/t/mismatch-between-asserts-semantics-and-how-its-used-o-oo-disable/29282/8 "2023-07-09T02:32:28Z")

</div>

> [@SonOfLilit](#):
>
> `assert __debug__ and condition, message`

I don’t think it does do what you want. You’d expect the assert to always pass if ` __debug__ ` is `False`, but instead it would always fail every time.

---

<div class="post-metadata">

**Author:** ![jamestwebber](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/jamestwebber/32/12799_2.png) [@jamestwebber](https://discuss.python.org/u/jamestwebber)\
**Post date:** [July 9, 2023, 2:56am UTC](https://discuss.python.org/t/mismatch-between-asserts-semantics-and-how-its-used-o-oo-disable/29282/9 "2023-07-09T02:56:14Z")

</div>

> [@jrivers](#):
>
> I don’t think it does do what you want. You’d expect the assert to always pass if ` __debug__ ` is `False`, but instead it would always fail every time.

Yeah…If the idea is to replace `-O` and `-OO` with versions that don’t strip `asserts`, this changes subtly wrong code into crashing code. I think it should be `assert (not __debug__ ) or condition`, and maybe the optimizing flags are primed to notice that construction and skip it entirely.

---

<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:** [July 9, 2023, 6:46am UTC](https://discuss.python.org/t/mismatch-between-asserts-semantics-and-how-its-used-o-oo-disable/29282/10 "2023-07-09T06:46:40Z")

</div>

> [@Rosuav](#):
>
> But maybe I’m the wrong person to be discussing this, since I have never used assert for anything that I wouldn’t have been willing to write as a comment.

IMO that’s _exactly_ the right way to look at assertions. I do the same. And I object to this proposal because it penalises people who do the right thing, while rewarding people who do the wrong thing (by changing the language to accommodate them).

---

<div class="post-metadata">

**Author:** ![SonOfLilit](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/sonoflilit/32/13312_2.png) [@SonOfLilit](https://discuss.python.org/u/SonOfLilit)\
**Post date:** [July 9, 2023, 7:18am UTC](https://discuss.python.org/t/mismatch-between-asserts-semantics-and-how-its-used-o-oo-disable/29282/11 "2023-07-09T07:18:28Z")

</div>

Wow, what an embarrassing mistake. Edited. Thank you.

---

<div class="post-metadata">

**Author:** ![SonOfLilit](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/sonoflilit/32/13312_2.png) [@SonOfLilit](https://discuss.python.org/u/SonOfLilit)\
**Post date:** [July 9, 2023, 7:28am UTC](https://discuss.python.org/t/mismatch-between-asserts-semantics-and-how-its-used-o-oo-disable/29282/12 "2023-07-09T07:28:32Z")

</div>

> [@pf\_moore](#):
>
> And I object to this proposal because it penalises people who do the right thing

I object to this, I think making it easy to write assertions that run in production and possible but a bit harder to write assertions that only run in debug is the opposite of penalizing people. It’s making python more pythonic. We don’t have to count cycles here, this is not the 80s 🙂

But also, I think that ship has sailed. All those people who do the right thing can’t use -O today because the stdlib and their other dependencies are full of assertions that we _would_ mind replacing with comments. This proposal fixes that so they can start using -O fearlessly.

---

<div class="post-metadata">

**Author:** ![Rosuav](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/rosuav/32/3429_2.png) [@Rosuav](https://discuss.python.org/u/Rosuav)\
**Post date:** [July 9, 2023, 8:22am UTC](https://discuss.python.org/t/mismatch-between-asserts-semantics-and-how-its-used-o-oo-disable/29282/13 "2023-07-09T08:22:21Z")

</div>

> [@SonOfLilit](#):
>
> > [@pf\_moore](#):
> >
> > And I object to this proposal because it penalises people who do the right thing
> 
> I object to this, I think making it easy to write assertions that run in production and possible but a bit harder to write assertions that only run in debug is the opposite of penalizing people. It’s making python more pythonic. We don’t have to count cycles here, this is not the 80s 🙂

In cases where it’s PURELY a matter of performance, you aren’t entirely wrong - for example, repeated addition onto a string _can_ be made faster under some circumstances, and CPython has an optimization for this. But the difference between repeated addition and `"".join(items)` is not one of correctness; they’ll both reach the same result, just that one might be horribly suboptimal.

Where in the stdlib are assertions used that mean that we can’t trust a -O run? Those should simply be bugs to be fixed.

---

<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:** [July 9, 2023, 9:55am UTC](https://discuss.python.org/t/mismatch-between-asserts-semantics-and-how-its-used-o-oo-disable/29282/14 "2023-07-09T09:55:14Z")

</div>

> [@SonOfLilit](#):
>
> I think making it easy to write assertions that run in production and possible but a bit harder to write assertions that only run in debug is the opposite of penalizing people.

It means expecting people whose code is _already correct_ to make changes. That’s penalising them when their code is currently correct.

> [@Rosuav](#):
>
> Where in the stdlib are assertions used that mean that we can’t trust a -O run? Those should simply be bugs to be fixed.

Precisely. And more generally, if _anyone_ has code that does the wrong thing when run under `-O`, then either that’s a bug they should fix, or they should state that they don’t support running their code under `-O` (and be prepared for the fact that other people may ask them to fix their code because "won’t run under `-O` isn’t a reasonable limitation to have…).

I’m honestly rather baffled that people think it’s reasonable to change the language because some people failed to understand how an existing statement works.

---

<div class="post-metadata">

**Author:** ![SonOfLilit](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/sonoflilit/32/13312_2.png) [@SonOfLilit](https://discuss.python.org/u/SonOfLilit)\
**Post date:** [July 9, 2023, 11:58am UTC](https://discuss.python.org/t/mismatch-between-asserts-semantics-and-how-its-used-o-oo-disable/29282/15 "2023-07-09T11:58:02Z")

</div>

> [@pf\_moore](#):
>
> I’m honestly rather baffled that people think it’s reasonable to change the language because some people failed to understand how an existing statement works.

This feature is more often misunderstood than not, to a point that there are at least dozens of offenders in the stdlib alone. See e.g. most uses of assert in `lib/Threading.py`.

So we’re proposing to deprecate it (specifically, -O) and replace it with a differently-named and better-designed feature that won’t get misused in this way. As a nice side-effect, we retcon almost all existing usages to be correct, making -O (in its new form, -O1) usable again. We’re making things more explicit and failures less silent, two Python principles. The only negative changes we introduce are very rare performance regressions (the only material one I’ve ever heard of is `click` CLI loading times, and I’ll personally fix that one) that are easy to fix.

---

<div class="post-metadata">

**Author:** ![thejcannon](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/thejcannon/32/23759_2.png) [@thejcannon](https://discuss.python.org/u/thejcannon)\
**Post date:** [July 9, 2023, 12:01pm UTC](https://discuss.python.org/t/mismatch-between-asserts-semantics-and-how-its-used-o-oo-disable/29282/16 "2023-07-09T12:01:20Z")

</div>

Another data point, some enterprise “security scanners” flag every assert primarily because of this issue/confusion. OTOH other tools of the same nature get upset when you don’t turn off ` __debug__ `.

We recently got flagged by 11k “violations” in our code for asserts.

So it isn’t just devs misunderstanding, but also enterprise security tools.

I agree with OP that the current state of things isn’t ideal.

---

<div class="post-metadata">

**Author:** ![Rosuav](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/rosuav/32/3429_2.png) [@Rosuav](https://discuss.python.org/u/Rosuav)\
**Post date:** [July 9, 2023, 12:43pm UTC](https://discuss.python.org/t/mismatch-between-asserts-semantics-and-how-its-used-o-oo-disable/29282/17 "2023-07-09T12:43:39Z")

</div>

> [@SonOfLilit](#):
>
> See e.g. most uses of assert in `lib/Threading.py`.

Okay. Let’s do a survey. Line numbers will be from a 3.12 pre-alpha, taken from a fresh pull as of today (2023-07-09), but it shouldn’t make a material difference.

- Line 718, `Barrier._enter()`:  
`assert self._state == 0`  
Looks correct. It’s asserting that an internal attribute has the one remaining possibility, after waiting until it’s in neither two and then testing if it’s below zero. Presumably the
- Line 743, `Barrier._wait()`:  
`assert self._state == 1`  
Just like the previous one.
- Line 884, `Thread. __init__ ()`:  
`assert group is None, "group argument must be None for now"`  
This one’s borderline, since it’s using an assert to test a function argument, but it’s an argument that has no meaning currently, so nobody should ever be passing it at all. And if you DO pass that argument, it won’t do anything, so even with the assertion ignored, it’s not going to cause any problems.
- Line 939, `Thread. __repr__ ()`:  
`assert self._initialized, "Thread. __init__ () was not called"`  
Unsure on this. Under what circumstances can you get the repr of something that hasn’t been initialized?
- Line 1077, `Thread._stop()`:  
`assert not lock.locked()`  
Internal method that is ensuring that internal state is correct (the `lock` here came from `self._tstate_lock`).
- Line 1142, `Thread._wait_for_tstate_lock()`:  
`assert self._is_stopped`  
Another internal method, another test of internal state.
- Lines 1167, 1172, 1184, 1196, 1207, 1225:  
`assert self._initialized, "Thread. __init__ () not called"`  
I suppose you could argue that this is wrong, but if you’re not calling an object’s initializer and then get peculiar AttributeErrors, it’s on you.
- Lines 1454 and 1458, DummyThread methods:  
Basic checks for stuff you can’t actually do with dummy threads.
- Line 1579-80, `_shutdown()`:  
`assert tlock is not None`  
`assert tlock.locked()`  
Internal method testing internal state.
- Line 1676, `_after_fork()`:  
`assert len(_active) == 1`  
Internal method testing internal state.

So there are a couple of dubious ones, but I absolutely would NOT agree that “most” uses of assert are incorrect here. Earlier, you claimed:

> [@SonOfLilit](#):
>
> `stdlib` is full of assertions that check for things determined by the non-stdlib caller, which means they’re broken in `-O`.

which, if it is indeed true, certainly isn’t supported by what I can find here. There are really only two ways that this could be triggered by the caller are (a) passing a parameter that shouldn’t be passed, and which currently does nothing; and (b) subclassing and failing to call init. Or, of course, messing with internal state, but then all bets are off anyway.

---

<div class="post-metadata">

**Author:** ![Rosuav](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/rosuav/32/3429_2.png) [@Rosuav](https://discuss.python.org/u/Rosuav)\
**Post date:** [July 9, 2023, 12:47pm UTC](https://discuss.python.org/t/mismatch-between-asserts-semantics-and-how-its-used-o-oo-disable/29282/18 "2023-07-09T12:47:14Z")

</div>

> [@thejcannon](#):
>
> Another data point, some enterprise “security scanners” flag every assert primarily because of this issue/confusion. OTOH other tools of the same nature get upset when you don’t turn off ` __debug__ `.

Well, if that’s what you have to work with, there’s not a lot of point changing the assert statement, since it wouldn’t be accepted anyway. But you will please permit me for considering this rule ridiculous.

---

<div class="post-metadata">

**Author:** ![thejcannon](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/thejcannon/32/23759_2.png) [@thejcannon](https://discuss.python.org/u/thejcannon)\
**Post date:** [July 9, 2023, 1:32pm UTC](https://discuss.python.org/t/mismatch-between-asserts-semantics-and-how-its-used-o-oo-disable/29282/19 "2023-07-09T13:32:05Z")

</div>

It is ridiculous, I almost laughed myself out of my chair.

But Theresa nugget of reality in it. The thinking is that a lot of people don’t know that asserts can be turned off (and by a flag with a name that doesn’t lend itself to knowing it turns off asserts) and so they might use asserts for actual validation. It’s extremely plausible, and likely comes from having seen it happen before.

So, as dumb as “don’t use asserts” is. It can be a realistic nugget of wisdom in the greater community. It’s dumb to you and I, but not so dumb for the layperson

---

<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:** [July 9, 2023, 1:39pm UTC](https://discuss.python.org/t/mismatch-between-asserts-semantics-and-how-its-used-o-oo-disable/29282/20 "2023-07-09T13:39:23Z")

</div>

> [@SonOfLilit](#):
>
> See e.g. most uses of assert in `lib/Threading.py`.

I did a quick scan. None of the asserts I saw seemed wrong. They state that a certain condition is expected to be true (in the sense that it’s a bug in the code if it’s not - _not_ in the sense of validating user input or anything like that). These can be safely omitted under `-O` because they are not affecting the code’s behaviour under supported conditions.

I dispute your assertions that these are “offenders”. Please provide a _specific_ example of an assertion in the stdlib that is incorrect, in the sense that it checks a condition that can _actually_ happen, and where the `AssertionError` is an expected result of the code in that case. Or, to put it another way, please describe exactly how the assertion can be triggered by supported usage of the relevant code.

> [@SonOfLilit](#):
>
> So we’re proposing to deprecate it

To be precise, you’re proposing to deprecate code that is used _correctly_ by a lot of people. That’s a major compatibility breakage, and you don’t seem to appreciate that Python takes such breakage very, very seriously.

> [@SonOfLilit](#):
>
> As a nice side-effect, we retcon almost all existing usages to be correct

That is absolutely what I’m describing as “punishing the people who use the feature correctly”. You give an amnesty to people who don’t read the documentation and don’t use the language correctly, and expect people who _do_ use the language correctly to change their code.

> [@thejcannon](#):
>
> Another data point, some enterprise “security scanners” flag every assert primarily because of this issue/confusion.

Then they are wrong. Either report a bug to them, ignore their reports, or treat the alert as a warning - review the code and if it’s incorrect, fix it. If it’s correct, do nothing (and be glad your developers don’t make at least one common error).

> [@thejcannon](#):
>
> I agree with OP that the current state of things isn’t ideal.

I agree the current state isn’t ideal. We apparently aren’t documenting the assert statement well enough to stop people making mistakes when using it. We should fix that, by teaching correct usage better and helping people who are currently using `assert` incorrectly to fix their code.

[Next page](https://discuss.python.org/t/mismatch-between-asserts-semantics-and-how-its-used-o-oo-disable/29282.md?page=2)
