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:
- Command line startup:
<span>python -m pdb script.py arg1 arg2</span>
- Insert breakpoints in code:
import pdb; pdb.set_trace() # Python 3.7+
- 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 |
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
- Binary search method: Quickly narrow down the scope by commenting/enabling code blocks
- Minimal reproduction: Strip away unrelated code to create minimal test cases
- Version comparison: Use
<span>git bisect</span>
to locate the problematic commit - Environment isolation: Create a clean virtual environment to eliminate dependency conflicts
2. Debugging in Production Environment
Safe Debugging Solutions:
- Error monitoring (Sentry/ELK)
- Remote debugging tunnel (SSH port forwarding)
- 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:
- A systematic methodology
- An appropriate toolchain
- A wealth of experience
- 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.