Python compiler that transforms Python code into C/C++ extensions for high-performance computing.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Cython provides comprehensive debugging and profiling capabilities for analyzing and optimizing Cython code. These tools enable source-level debugging, performance analysis, and identification of bottlenecks in compiled extensions.
GDB-based debugger that enables source-level debugging of both Python and Cython code.
cygdb [options] [path-to-project-directory] [gdb-args...]
Options:
--gdb-executable GDB GDB executable to use (default: gdb)
--verbose Verbose output
-h, --help Show help
Requirements:
- cython_debug/ directory with debug information
- Python executable compiled with debug symbols
- GDB with Python supportCompiler directives and build options for debugging support.
# Compilation options for debugging
compiler_directives = {
'linetrace': True, # Enable line tracing
'binding': True, # Enable function binding
'profile': True, # Enable profiling hooks
'emit_code_comments': True, # Add code comments in C output
}
# Build with debugging information
cythonize("module.pyx", gdb_debug=True, **compiler_directives)Integration with Python profiling tools and performance analysis.
@cython.profile(True)
def profiled_function():
"""Function with profiling enabled."""
pass
@cython.linetrace(True)
@cython.binding(True)
def traced_function():
"""Function with line tracing for detailed profiling."""
passHTML annotation generation for performance analysis and optimization.
# Generate annotated HTML output
cython -a source.pyx # Basic annotation
cython -a --annotate-coverage coverage.xml source.pyx # With coverage data
# Via cythonize
cythonize --annotate source.pyx# setup.py for debug builds
from setuptools import setup
from Cython.Build import cythonize
debug_args = {
'gdb_debug': True,
'compiler_directives': {
'linetrace': True,
'binding': True,
'profile': True,
'emit_code_comments': True,
'language_level': 3,
}
}
setup(
ext_modules=cythonize("src/*.pyx", **debug_args),
zip_safe=False,
)# 1. Build with debug information
python setup.py build_ext --inplace --debug
# 2. Start debugging session
cygdb
# 3. In GDB, set breakpoints and run
(gdb) cy break module.pyx:42
(gdb) cy run
(gdb) cy step
(gdb) cy print variable_name
(gdb) cy list# Cython-specific GDB commands
(gdb) cy break my_module.fast_function # Break at Cython function
(gdb) cy step # Step through Cython code
(gdb) cy next # Next line in Cython code
(gdb) cy print cython_var # Print Cython variable
(gdb) cy print local_vars # Print all local variables
(gdb) cy list # List current Cython source
(gdb) cy bt # Cython backtrace
(gdb) cy up # Move up Cython call stack
(gdb) cy down # Move down Cython call stack%load_ext cython
%%cython --gdb
def debug_function(int n):
cdef int i, total = 0
for i in range(n):
total += i * i # Breakpoint can be set here
return total
# Function is compiled with debug information
result = debug_function(100)import cProfile
import pstats
# Enable profiling in Cython
%%cython -X profile=True -X linetrace=True -X binding=True
def slow_function(int n):
cdef int i, result = 0
for i in range(n):
result += expensive_operation(i)
return result
def expensive_operation(int x):
return x * x * x
# Profile the function
cProfile.run('slow_function(10000)', 'profile_stats')
# Analyze results
stats = pstats.Stats('profile_stats')
stats.sort_stats('cumulative')
stats.print_stats()# Install: pip install line_profiler
%load_ext line_profiler
%%cython -X linetrace=True -X binding=True
@profile
def line_profiled_function(double[:] arr):
cdef int i
cdef double total = 0.0
cdef int n = arr.shape[0]
for i in range(n): # This line will be profiled
total += arr[i] * 2.0 # This line will be profiled
return total
# Run with line profiler
%lprun -f line_profiled_function line_profiled_function(data)# Install: pip install memory_profiler
%load_ext memory_profiler
%%cython -X profile=True
@profile
def memory_intensive_function(int n):
cdef list data = []
cdef int i
for i in range(n):
data.append(i * i) # Memory allocation tracked
return sum(data)
# Profile memory usage
%mprun -f memory_intensive_function memory_intensive_function(100000)# After running: cython -a my_module.pyx
# Open my_module.html in browser
%%cython -a
import numpy as np
cimport numpy as cnp
def analyze_performance(cnp.double_t[:] data):
"""Function to analyze with annotations."""
cdef int i
cdef double total = 0.0
cdef int n = data.shape[0]
# Yellow lines indicate Python interaction overhead
# White lines indicate pure C code
for i in range(n):
total += data[i] # Should be white (fast)
return total # May be yellow (Python object creation)# 1. Run tests with coverage
python -m pytest --cov=my_module --cov-report=xml
# 2. Generate annotated output with coverage data
cython -a --annotate-coverage coverage.xml my_module.pyx
# 3. View coverage-annotated HTML
# Green highlighting shows well-tested code
# Red highlighting shows untested code paths# For debugging at the C level
%%cython --gdb -X emit_code_comments=True
def c_level_debug(int x):
cdef int* ptr = <int*>malloc(sizeof(int) * 10)
if ptr == NULL:
raise MemoryError("Failed to allocate memory")
ptr[0] = x # Can inspect C-level memory in GDB
cdef int result = ptr[0] * 2
free(ptr)
return resultimport timeit
%%cython -X boundscheck=False -X wraparound=False -X cdivision=True
def optimized_function(double[:] data):
cdef int i
cdef double total = 0.0
cdef int n = data.shape[0]
for i in range(n):
total += data[i]
return total
# Benchmark against Python version
import numpy as np
data = np.random.random(1000000)
cython_time = timeit.timeit(
lambda: optimized_function(data),
number=100
)
python_time = timeit.timeit(
lambda: sum(data),
number=100
)
print(f"Cython: {cython_time:.4f}s")
print(f"Python: {python_time:.4f}s")
print(f"Speedup: {python_time/cython_time:.2f}x")# Verbose compilation for debugging build problems
cython --verbose my_module.pyx
# Generate intermediate C code for inspection
cython --output-file my_module.c my_module.pyx
# Check generated C code
less my_module.c
# Debug compilation errors
cython -Werror my_module.pyx # Treat warnings as errors# Create .cygdbinit file for custom GDB commands
echo "set print pretty on" > .cygdbinit
echo "set pagination off" >> .cygdbinit
echo "define cy-locals" >> .cygdbinit
echo " cy print local_vars" >> .cygdbinit
echo "end" >> .cygdbinit
# Use custom configuration
cygdb --gdb-executable gdb-multiarch# VS Code configuration for Cython debugging
# In .vscode/launch.json:
{
"name": "Python: Cython Debug",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}/test_script.py",
"console": "integratedTerminal",
"justMyCode": false,
"env": {
"CYTHON_DEBUG": "1"
}
}The debugging and profiling capabilities in Cython provide comprehensive tools for analyzing performance bottlenecks, identifying optimization opportunities, and debugging both Python and C-level code in compiled extensions.
Install with Tessl CLI
npx tessl i tessl/pypi-cython