python -O does the following currently:

  • completely ignores asserts
  • sets the special builtin name __debug__ to False (which by default is True)

and when called as python -OO

  • removes docstrings from the code

I don't know why everyone forgets to mention the __debug__ issue; perhaps it is because I'm the only one using it :) An if __debug__ construct creates no bytecode at all when running under -O, and I find that very useful.

Answer from tzot on Stack Overflow
🌐
Python.org
discuss.python.org › ideas
Does anyone use `-O` or `-OO` or `PYTHONOPTIMIZE=1` in their deployments? - Ideas - Discussions on Python.org
November 1, 2023 - I expect the answer to the question in the subject for most is “No”… In that case, you are not who I’m interested in hearing from. It’d be good to hear from CPython users who actually use -O, -OO, or PYTHONOPTIMIZE=1 to have Python elide assert statements (performance?) or (-OO) omit docstrings from bytecode (memory savings?). Some idea of: Why you do it?
Discussions

optimization - What are the implications of running python with the optimize flag? - Stack Overflow
What does Python do differently when running with the -O (optimize) flag? More on stackoverflow.com
🌐 stackoverflow.com
May 14, 2010
Stop ignoring asserts when running in optimized mode - Ideas - Discussions on Python.org
Following a Twitter discussion, I was interested to get some feedback around the idea of making a PEP to have assert statements always execute, independently of Python’s optimize mode. I will be taking some time in the near future to lay out what I think can be the pros and cons, but if some ... More on discuss.python.org
🌐 discuss.python.org
6
January 13, 2022
Usage of assert statements in optimized mode
I've noticed that Lark uses assert statements in some places outside of tests. Just by doing git grep assert in the lark directory we can see a big list of these. Assert statements are ignored when Python is running in optimized mode. Op... More on github.com
🌐 github.com
2
July 13, 2018
What does Python optimization (-O or PYTHONOPTIMIZE) do? - Stack Overflow
The docs only say that Python interpreter performs "basic optimizations", without going into any detail. Obviously, it's implementation dependent, but is there any way to get a feel for what type of More on stackoverflow.com
🌐 stackoverflow.com
🌐
Real Python
realpython.com › lessons › pythonoptimize-variable
Setting the PYTHONOPTIMIZE Environment Variable (Video) – Real Python
03:03 You can use any integer number to set PYTHONOPTIMIZE, but Python only implements two levels of optimization. Using a number greater than 2 has no real effect on your compiled bytecode. 03:15 Setting PYTHONOPTIMIZE to 0 will cause the interpreter to return to normal mode.
Published   April 25, 2023
🌐
Python.org
discuss.python.org › ideas
Stop ignoring asserts when running in optimized mode - Ideas - Discussions on Python.org
January 13, 2022 - Following a Twitter discussion, I was interested to get some feedback around the idea of making a PEP to have assert statements always execute, independently of Python’s optimize mode. I will be taking some time in the near future to lay out what I think can be the pros and cons, but if some ...
🌐
GitHub
github.com › python › typing › discussions › 1598
Type hints and optimized mode · python/typing · Discussion #1598
While reviewing a PR I came across a somewhat interesting case - the validity of the return type depending on whether Python is running in optimized mode (starting Python with -O or PYTHONOPTIMIZE ...
Author   python
Find elsewhere
🌐
GitHub
github.com › lark-parser › lark › issues › 185
Usage of assert statements in optimized mode · Issue #185 · lark-parser/lark
July 13, 2018 - Assert statements are ignored when Python is running in optimized mode. Optimize mode is used in some projects when Python is deployed and/or distributed.
Author   petermlm
🌐
Medium
medium.com › @bremer_21076 › how-to-optimize-python-code-the-right-way-a-beginners-guide-to-profiling-34c4c0f07dc4
How to optimize Python code the right way — a beginners guide to profiling | by Klaus Bremer | Medium
November 28, 2023 - Optimized code is often harder to maintain and that should be avoided. However—sometimes the code is not fast enough and a speed-up is necessary. Then people often try to guess where to start to make the code faster. This is a bad idea and sometimes even experienced Python programmers are surprised about the real bottlenecks.
🌐
GitHub
github.com › astral-sh › uv › issues › 11547
Add support for optimized mode (`-O`) in `uv run` · Issue #11547 · astral-sh/uv
February 16, 2025 - The standard CPython interpreter has a handful of flags that can be set when executing a Python program, most of which are not directly supported by uv run. Do the uv maintainers have any plans to support additional flags, specifically the following optimization-related flags?
Author   gusutabopb
🌐
Python
wiki.python.org › moin › PythonSpeed › PerformanceTips
PythonSpeed/PerformanceTips - Python Wiki
Which method is appropriate will depend on what version of Python you're using and the characteristics of the data you are manipulating. Guido van Rossum wrote a much more detailed (and succinct) examination of loop optimization that is definitely worth reading.
🌐
Real Python
realpython.com › python-assert-statement
Python's assert: Debug and Test Your Code Like a Pro – Real Python
January 12, 2025 - This is the default or normal Python mode, in which all your assertions are enabled because __debug__ is True. On the other hand, if __debug__ is False, then the code under the outer if statement doesn’t run, meaning that your assertions will be disabled. In this case, Python is running in optimized mode.
🌐
Reddit
reddit.com › r/python › how to optimize python code?
r/Python on Reddit: How to optimize python code?
January 28, 2022 -

Hi Pythonistas,

I'm interested in learning what optimization techniques you know for python code. I know its a general statement, but I'm interested in really pushing execution to the maximum.

I use the following -

  1. I declare __slots__ in custom classes

  2. I use typing blocks for typing imports

  3. I use builtins when possible

  4. I try to reduce function calls

  5. I use set lookups wherever possible

  6. I prefer iteration to recursion

Edit: I am using a profiler, and benchmarks. I'm working on a library - an ASGI Api framework. The code is async. Its not darascience. Its neither compatible with pypy, nor with numba..

What else?

🌐
Atleastfornow
atleastfornow.net › posts › py3-enable-optimisations
Compile-time Optimisations on Python 3 · atleastfornow.net
Firstly, you are doing the whole compile twice (first profiler-enabled, then optimised), as well as running the entirety of your representative code suite. On my computer the compile time (using make -j8) went from 1 minute to 24 minutes. This isn’t so bad if you’re compiling one Python to keep around for good, but when you’re compiling 38 variants on public CI, it can be unacceptable – which is why the Docker-official Python images don’t have it enabled.
🌐
Toucan
toucantoco.com › en › tech-blog › python-performance-optimization
Profiling and optimizing your Python code
Sure, Python is not compiled to optimized native code (yet) and therefore won’t rival C, Fortran or assembly in tightly nested loops. But most Python performance issues can be alleviated by improving the algorithm or using the right tool for the job.
🌐
Medium
medium.com › @jeffmarvel › a-brief-exploration-of-optimization-in-python-4877d48b2420
A Brief Exploration of Optimization in Python | by Jeff Marvel | Medium
September 27, 2021 - As anyone who has begun working in python will know, Scipy contains a number of useful packages covering a range of functions from statistics to linear algebra. Scipy has an Optimize package to help solve problems similar to what we faced in Treasury. The foundational math is linear algebra, and at its simplest, the functions included in Scipy Optimize are all essentially solvers designed to find the solution to a series of equations.
Top answer
1 of 1
7

It's not much compilation per se (CPython does compile to bytecode), but the extremely dynamic nature of the language hampers "traditional" optimizations, which are guided by invariants which are difficult to check at compile time in Python, because the semantics of the language is such that most information about what the code is actually supposed to do is only available at runtime.

Your if condition == True: example is a good one: that comparison could be optimized only if the compiler could prove that condition is always a boolean, which is a non-trivial task if it derives from anything but literals in the current scope - and if it could prove that, at runtime, nobody managed to overwrite True with something else (possible only in Python 2 IIRC).

Mind you, some type inference is possible, and it's actually how code completion tools like Jedi work; however, Jedi can take some shortcuts and assume e.g. some kind of standard environment, while the interpreter has to cope with the most bizarre modifications to the globals that the language do allow.

So, in general CPython does not try very hard to optimize anything - actually, it doesn't seem to do any kind of "smart" code analysis, AFAICT they mostly try to build an efficient but "mostly vanilla" interpreter. So, expect to pay almost exactly for what you write, there's no optimizer to save sloppy code.

By the way, your and example is not an optimization done by the interpreter, it's just how the semantic of the operator is defined (and it's quite crucial that it's specified that and and or do short circuit evaluation and it's not an optional "optimization", since it could alter the observable behavior of the program if the right hand operand had side effects).

A better approach for a language that dynamic is instead that of a tracing JIT - the interpreter lets the code run for a while, and observes the invariants that seem to hold well (for example, condition seems to always be a boolean, True is always True, some variable is always an integer, ...), and then uses this information to compile to machine code an optimized version of the code. This is let run as long as the invariants above do hold - but as soon as one of the premises used to compile the optimized version is broken, the execution goes back into interpreted mode, and tracing begins again to find out if a new optimized version can be built.

Thus, the typical case is optimized well, applying the usual optimization techniques, but whenever something bizarre (but allowed by the language) happens, the runtime can fallback to the regular "literal" bytecode interpretation.

This is the approach used to squeeze good performance from most dynamic languages (most modern JavaScript engines use some variation of this basic approach), and in Python is used in PyPy.