脚本如何逐行统计代码运行耗时

wen 实用脚本 26

本文目录导读:

脚本如何逐行统计代码运行耗时

  1. 手动计时器(最基础)
  2. 装饰器方式(适用于函数内)
  3. 使用line_profiler(专业逐行分析)
  4. 上下文管理器(灵活控制)
  5. 自动化行级计时器(高级)
  6. 集成到IDE(最实用)
  7. 推荐使用方法

手动计时器(最基础)

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工具:

  1. 点击"Run" -> "Profile 'your_script'"
  2. 运行后查看"Call Graph"或"Statistics"
  3. 双击函数查看逐行耗时

推荐使用方法

  • 简单调试:使用上下文管理器(方法4)
  • 性能分析:安装line_profiler(方法3)
  • 生产环境:使用IDE集成的Profiler(方法6)
  • 自动化测试:结合unittest和装饰器

注意事项

  1. 逐行计时会引入额外性能开销
  2. 对于毫秒级操作,统计结果可能不准确
  3. 建议多次运行取平均值
  4. 考虑GIL对多线程的影响

选择哪种方法取决于你的具体需求和场景复杂度。

抱歉,评论功能暂时关闭!