本文目录导读:

手动计时器(最基础)
import time
def manual_timer():
# 行1
start = time.time()
result = sum(range(1000000))
print(f"行1耗时: {time.time() - start:.4f}秒")
# 行2
start = time.time()
result = [i**2 for i in range(10000)]
print(f"行2耗时: {time.time() - start:.4f}秒")
# 行3
start = time.time()
time.sleep(0.5)
print(f"行3耗时: {time.time() - start:.4f}秒")
manual_timer()
装饰器方式(适用于函数内)
import time
from functools import wraps
def timer_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
print(f"{func.__name__} 总耗时: {time.time() - start:.4f}秒")
return result
return wrapper
@timer_decorator
def my_function():
time.sleep(0.5)
result = sum(range(1000000))
return result
my_function()
使用line_profiler(专业逐行分析)
# 首先安装: pip install line_profiler
# 创建测试文件 test_profiler.py
@profile
def slow_function():
total = 0
for i in range(100000):
total += i ** 2
return total
# 在命令行运行:
# kernprof -l -v test_profiler.py
上下文管理器(灵活控制)
import time
from contextlib import contextmanager
class LineTimer:
def __init__(self):
self.times = {}
self.current_line = 0
@contextmanager
def measure(self, line_name=None):
start = time.time()
yield
elapsed = time.time() - start
if line_name:
self.times[line_name] = elapsed
else:
self.current_line += 1
self.times[f"行{self.current_line}"] = elapsed
def report(self):
print("\n=== 代码行耗时统计 ===")
for line, duration in self.times.items():
print(f"{line}: {duration:.4f}秒")
# 使用示例
timer = LineTimer()
with timer.measure("初始化"):
data = list(range(1000000))
with timer.measure("计算平方和"):
result = sum(x**2 for x in data)
with timer.measure("排序"):
sorted_data = sorted(data, reverse=True)
timer.report()
自动化行级计时器(高级)
import time
import sys
import traceback
class LineProfiler:
def __init__(self):
self.timings = {}
self.current_func = None
self.line_start = {}
def trace_calls(self, frame, event, arg):
if event == 'call':
self.current_func = frame.f_code.co_name
self.line_start[frame.f_lineno] = time.time()
elif event == 'line':
if frame.f_lineno in self.line_start:
elapsed = time.time() - self.line_start[frame.f_lineno]
key = (self.current_func, frame.f_lineno)
self.timings[key] = self.timings.get(key, 0) + elapsed
self.line_start[frame.f_lineno] = time.time()
elif event == 'return':
if frame.f_lineno in self.line_start:
elapsed = time.time() - self.line_start[frame.f_lineno]
key = (self.current_func, frame.f_lineno)
self.timings[key] = self.timings.get(key, 0) + elapsed
return self.trace_calls
# 使用示例
profiler = LineProfiler()
def test_function():
total = 0
for i in range(1000):
total += i ** 2
time.sleep(0.001)
return total
# 设置追踪
sys.settrace(profiler.trace_calls)
result = test_function()
sys.settrace(None)
# 输出结果
print("\n=== 逐行耗时统计 ===")
for (func, line), duration in sorted(profiler.timings.items()):
print(f"{func}:{line} - {duration:.4f}秒")
集成到IDE(最实用)
使用PyCharm的Profiler工具:
- 点击"Run" -> "Profile 'your_script'"
- 运行后查看"Call Graph"或"Statistics"
- 双击函数查看逐行耗时
推荐使用方法
- 简单调试:使用上下文管理器(方法4)
- 性能分析:安装line_profiler(方法3)
- 生产环境:使用IDE集成的Profiler(方法6)
- 自动化测试:结合unittest和装饰器
注意事项:
- 逐行计时会引入额外性能开销
- 对于毫秒级操作,统计结果可能不准确
- 建议多次运行取平均值
- 考虑GIL对多线程的影响
选择哪种方法取决于你的具体需求和场景复杂度。