Understanding Python Code Object Compiler Flags

Python code objects represent executable chunks of bytecode and store crucial execution metadata in a bitmask attribute called co_flags. This article breaks down what compiler flags are and specifically examines three essential flags: CO_OPTIMIZED, CO_NEWLOCALS, and CO_VARKEYWORDS. You will learn how these flags inform the CPython interpreter about a code block's scoping rules, argument handling, and internal variable optimizations.

What Are Code Object Flags?

When Python compiles source code into bytecode, it creates a types.CodeType object containing instructions, constants, variable names, and execution metadata. The co_flags attribute on a code object is an integer representing a bitwise mask of compilation flags. These flags tell the CPython virtual machine how to construct stack frames, allocate namespaces, and bind arguments at runtime.

You can inspect a function's flags directly using the inspect module or by querying func.__code__.co_flags.

CO_OPTIMIZED (Value: 0x0001)

The CO_OPTIMIZED flag indicates that the code object uses optimized local variable access.

In module-level code or class definitions, local variables are dynamically stored and accessed via a dictionary namespace. In contrast, standard functions have a fixed set of local variables known at compile time. When CO_OPTIMIZED is set:

CO_NEWLOCALS (Value: 0x0002)

The CO_NEWLOCALS flag signals to the Python virtual machine that a new local namespace dictionary must be constructed when the code block executes.

In standard function definitions, CO_OPTIMIZED and CO_NEWLOCALS are almost always enabled together.

CO_VARKEYWORDS (Value: 0x0008)

The CO_VARKEYWORDS flag denotes that a function accepts arbitrary keyword arguments, defined in the source code using the double-asterisk syntax (e.g., **kwargs).

When the interpreter invokes a function:

Checking Flags in Python

CPython exposes these flag definitions in the standard library's dis module. You can check for their presence using bitwise operations:

import dis

def example_function(a, **kwargs):
    b = 10
    return a + b

flags = example_function.__code__.co_flags

print(bool(flags & dis.COMPILER_FLAG_NAMES[1]))   # CO_OPTIMIZED
print(bool(flags & dis.COMPILER_FLAG_NAMES[2]))   # CO_NEWLOCALS
print(bool(flags & dis.COMPILER_FLAG_NAMES[8]))   # CO_VARKEYWORDS

Understanding these flags provides insight into how CPython distinguishes standard functions from dynamic scopes and manages runtime performance behind the scenes.