Comprehensive Guide to Python Debugging: From Print to Advanced Techniques

Hello everyone, I am ICdoeWR.

As a Python developer, debugging is an essential part of our daily work. Mastering the methodologies, basic techniques, and advanced strategies for debugging Python code helps us quickly locate and resolve various issues in our code.

1. Debugging is Very Important!

Debugging is a critical step in the software development process for identifying, analyzing, and fixing errors. According to industry statistics, developers spend an average of over 50% of their time debugging. Efficient debugging skills can:

  • Significantly shorten the development cycle
  • Improve code quality
  • Reduce maintenance costs
  • Enhance understanding of program execution flow

2. Basic Debugging Methods

1. print() Debugging Method: Simple but Effective

Applicable Scenarios: Quickly verify variable values or execution flow

Advanced Techniques:

# Use f-string to enhance readability 
print(f"[DEBUG] Current x value: {x}, Type: {type(x)}, Memory Address: {id(x)}")
 
# Debug information with timestamp 
from datetime import datetime 
print(f"[{datetime.now().isoformat()}] Executed to step 2")

Pros and Cons Analysis:

  • ✅ Advantages: No additional tools required, immediate visibility
  • ❌ Disadvantages:
    • Requires manual cleanup of debug statements
    • Excessive use can lead to cluttered output
    • Cannot interactively inspect during runtime

2. Assertions: A Defensive Programming Tool

def calculate_average(nums):
  assert len(nums) > 0, "Input list cannot be empty"
  assert all(isinstance(x, (int, float)) for x in nums), "List must contain only numbers"
  return sum(nums)/len(nums)

Best Practices:

  • Used to validate conditions that “should never happen”
  • Can be used with custom exceptions
  • In production, can be disabled with the <span>-O</span> parameter

3. Professional Logging Systems

1. Standard Usage of the logging Module

import logging 
from logging.handlers import RotatingFileHandler 

# Multi-level logging configuration 
logging.basicConfig(
    level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(pathname)s:%(lineno)d - %(message)s',
    handlers=[
        RotatingFileHandler('app.log', maxBytes=10*1024*1024, backupCount=5),
        logging.StreamHandler()
    ]
)

logger = logging.getLogger(__name__)

# Usage example 
logger.debug("Debug information")
logger.info("General information")
logger.warning("Warning information")
logger.error("Error information", exc_info=True)  # Automatically logs exception stack trace 

Logging Level Explanation:

Level Usage Scenario
DEBUG Development debugging details
INFO General runtime information
WARNING Potential problem alerts
ERROR Functional errors
CRITICAL System-level errors

2. Advanced Structured Logging

Use <span>structlog</span> or <span>python-json-logger</span> to implement structured logging:

from pythonjsonlogger import jsonlogger 

logger = logging.getLogger()
logHandler = logging.StreamHandler()
formatter = jsonlogger.JsonFormatter(
'%(asctime)s %(name)s %(levelname)s %(message)s %(pathname)s %(lineno)d'
)
logHandler.setFormatter(formatter)
logger.addHandler(logHandler)

logger.info("User logged in", extra={
"user_id": 123,
"ip": "192.168.1.1",
"user_agent": "Mozilla/5.0"
})

Advantages:

  • Facilitates processing by log analysis systems (e.g., ELK)
  • Supports rich metadata
  • Easy to generate statistical reports

4. Deep Application of Debuggers

1. Detailed Explanation of the pdb Standard Debugger

Startup Methods:

  1. Command line startup:<span>python -m pdb script.py arg1 arg2</span>
  2. Insert breakpoints in code:
import pdb; pdb.set_trace()  # Python 3.7+
  1. Debug after exception:
python -m pdb -c continue script.py 

Core Command Quick Reference:

Command Abbreviation Function
next n Execute next line
step s Enter function call
continue c Continue execution to the next breakpoint
list l Display current code context
print p Print variable value
where w Display call stack
break b Set breakpoint
return r Execute to current function return
quit q Exit debugger

2. Recommended Enhanced Debuggers

ipdb – A debugger with IPython features:

import ipdb; ipdb.set_trace()

Features:

  • Syntax highlighting
  • Auto-completion
  • Better interactive experience

pdb++ – A feature-rich alternative:

pip install pdbpp 

Characteristics:

  • Color output
  • Label completion
  • Improved UI

5. Advanced Exception Handling Techniques

1. Precise Exception Capture

try:
    process_data(raw_data)
except (ValueError, IndexError) as e:
    logger.error(f"Data processing failed: {str(e)}", exc_info=True)
raise DataProcessingError("Data format error") from e 
except DatabaseError as e:
if "connection timeout" in str(e):
        retry_operation()
else:
raise
except Exception as e:
    logger.critical("Unhandled exception", exc_info=True)
raise
finally:
    cleanup_resources()

Best Practices:

  • Capture exceptions from specific to broad
  • Use <span>raise from</span> to preserve the original exception chain
  • Log complete stack information

2. Stack Trace Analysis

import traceback 
import sys 

def log_uncaught_exceptions(exc_type, exc_value, exc_traceback):
    logger.critical("Uncaught exception", 
                   exc_info=(exc_type, exc_value, exc_traceback))
    sys.__excepthook__(exc_type, exc_value, exc_traceback)

sys.excepthook = log_uncaught_exceptions 

try:
    risky_operation()
except Exception:
# Get stack string 
    stack_str = traceback.format_exc()
# Get stack object 
    stack_list = traceback.extract_tb(sys.exc_info()[2])
for frame in stack_list:
print(f"File: {frame.filename}, Line Number: {frame.lineno}, Function: {frame.name}")

6. Static Analysis and Code Inspection

1. Linter Tool Comparison

Tool Features Applicable Scenarios
flake8 PEP8 compliance check Code style unification
pylint Comprehensive code quality analysis Quality control for large projects
mypy Static type checking Type-annotated projects
bandit Security vulnerability checks Security-sensitive projects

Integrated Usage Example:

# Run multiple checks simultaneously 
flake8 . && pylint /*.py && mypy .

2. IDE Integrated Debugging

VS Code Configuration Example (.vscode/launch.json):

{
    "version":"0.2.0",
"configurations":[
{
"name":"Python: Current File",
"type":"python",
"request":"launch",
"program":"${file}",
"console":"integratedTerminal",
"args":["--input","data.json"],
"env":{"DEBUG":"true"},
"justMyCode":false
},
{
"name":"Python: Remote Attach",
"type":"python",
"request":"attach",
"port":5678,
"host":"localhost"
}
]
}

Highlights of PyCharm Debugging Features:

  • Visual variable monitoring
  • Conditional breakpoints
  • Exception breakpoints
  • Interactive console
  • Scientific mode (array visualization)

7. Unit Testing and Debugging

1. Advanced Usage of pytest

conftest.py 
import pytest 

@pytest.fixture 
def db_connection():
    conn = create_test_connection()
yield conn 
    conn.close()

test_module.py 
def test_data_processing(db_connection):
    result = process_data(db_connection, test_input)
assert result == expected_output 
assert not result.is_empty()
assert "error" not in result.logs 

Debugging Test Techniques:

# Enter pdb when a test fails 
pytest --pdb 
 
# Run only specific tests 
pytest -k "test_data_processing"
 
# Show detailed output 
pytest -v 

2. Test Coverage Analysis

# Generate coverage report 
coverage run -m pytest 
coverage html 
coverage report -m 
 
# Check only new code coverage 
coverage diff 

Coverage Goals:

  • Core modules: >=90%
  • Utility classes: >=80%
  • Scripts: >=60%

8. Advanced Debugging Techniques

1. Post-mortem Debugging

import pdb 
 
def main():
    try:
        run_application()
    except Exception:
        pdb.post_mortem()  # Automatically enter debugger after exception 

2. Remote Debugging Practice

Use <span>web-pdb</span> for web-based remote debugging:

import web_pdb; web_pdb.set_trace()

Access <span>http://localhost:5555</span> to debug

3. Performance Analysis Techniques

Example of using cProfile:

import cProfile 

def profile_func():
# Code to analyze 
pass

# Generate statistics file 
cProfile.run('profile_func()', 'profile_stats')

# Analyze hotspots 
import pstats 
stats = pstats.Stats('profile_stats')
stats.sort_stats('cumulative').print_stats(10)

Recommended Visualization Tools:

  • <span>snakeviz</span>: Generates interactive flame graphs
  • <span>py-spy</span>: Low-overhead sampling profiler
  • <span>memory_profiler</span>: Memory usage analysis

9. Systematic Debugging Strategies

1. Problem Localization Methodology

  1. Binary search method: Quickly narrow down the scope by commenting/enabling code blocks
  2. Minimal reproduction: Strip away unrelated code to create minimal test cases
  3. Version comparison: Use <span>git bisect</span> to locate the problematic commit
  4. Environment isolation: Create a clean virtual environment to eliminate dependency conflicts

2. Debugging in Production Environment

Safe Debugging Solutions:

  1. Error monitoring (Sentry/ELK)
  2. Remote debugging tunnel (SSH port forwarding)
  3. Diagnostic endpoints (authentication required)
@app.route('/_debug', methods=['POST'])
def debug_endpoint():
    if not validate_token(request):
        abort(403)
    code = request.json.get('code')
    return jsonify({'result': str(eval(code))})

10. Recommended Tool Ecosystem

Category Recommended Tools
Debuggers pdbpp, ipdb, PuDB
Performance Analysis py-spy, scalene, pyinstrument
Log Management structlog, loguru, sentry-sdk
Testing Frameworks pytest, unittest, hypothesis
Visual Debugging PyCharm, VS Code, Thonny
Online Tools PythonTutor (code visualization), Debuggex (regex debugging)

Become a Python Debugging Expert

By combining the above methods, developers can systematically improve debugging efficiency, quickly locate and resolve issues in code, and become experts in Python debugging.

Efficient debugging requires:

  1. A systematic methodology
  2. An appropriate toolchain
  3. A wealth of experience
  4. Patience and logical thinking

Keywords: Developers do not avoid bugs, but can quickly discover and resolve them.

Integrating debugging techniques into daily development will surely enhance our Python debugging capabilities!

Last updated: April 20, 2025Author: ICdoeWR

Note: Please indicate the source when reprinting.

Discussion: Feel free to leave comments in the comment section!

Author Bio: ICdoeWR, a full-stack developer focused on technology and programming, regularly shares practical programming tips and project experience. Continuously learning, adapting to changes, recording details, reflecting, and growing.

Important Note: This article mainly records my learning and practice process, and the content or views expressed only represent personal opinions, which I believe are not entirely correct. Please do not follow if you dislike.

Comprehensive Guide to Python Debugging: From Print to Advanced Techniques

Leave a Comment