Python技术迷

监控 Python 内存使用情况和代码执行时间

在写 Python 项目时,有时候你会发现,程序跑着跑着就开始“吃”内存,或者某个接口响应突然变慢。其实,很多性能问题不是算法复杂,而是你没搞清楚代码到底耗在哪儿。今天这篇文章,我们就聊聊怎么用几行 Python 代码监控内存和执行时间,让你写代码更有“底气”。

一、最简单的执行时间统计法

很多人调性能第一反应是加个 time.time(),这个没错,简单粗暴又实用。

import time

defslow_func():
    time.sleep(1)
return"done"

start = time.time()
result = slow_func()
end = time.time()

print(f"执行结果:{result}")
print(f"耗时:{end - start:.4f} 秒")

输出类似:

执行结果:done
耗时:1.0003 秒

不过这种方法不太方便在多个函数或模块间使用,建议用更优雅一点的方式,比如装饰器。

二、用装饰器统计函数耗时

装饰器其实就是在函数执行前后插入逻辑,非常适合这种性能监控场景。

import time
from functools import wraps

deftime_it(func):
    @wraps(func)
defwrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        end = time.perf_counter()
        print(f"{func.__name__} 执行耗时: {(end - start)*1000:.2f} ms")
return result
return wrapper

@time_it
defcalc():
    total = sum(range(1000000))
return total

calc()

time.perf_counter() 比 time.time() 更精准,适合微秒级别的性能分析。

三、监控内存使用情况(psutil)

光看时间还不够,有时候你会发现函数明明很快,但运行久了内存占用越来越多,这就得看“内存泄漏”或“缓存没清掉”的问题了。psutil 是个非常实用的库,能获取系统和进程的各种资源使用情况。

import os
import psutil
import time

process = psutil.Process(os.getpid())

defmemory_intensive():
    a = [i for i in range(1000000)]
    time.sleep(1)
return sum(a)

before = process.memory_info().rss / 1024 / 1024
memory_intensive()
after = process.memory_info().rss / 1024 / 1024

print(f"运行前内存: {before:.2f} MB")
print(f"运行后内存: {after:.2f} MB")
print(f"增长: {after - before:.2f} MB")

这段代码可以很直观地告诉你执行前后内存的变化。

四、用 tracemalloc 跟踪内存分配

如果你想知道到底哪一行代码占了内存,可以试试 Python 自带的 tracemalloc 模块。

import tracemalloc

defdemo():
    data = [x * 2for x in range(100000)]
return data

tracemalloc.start()

demo()

current, peak = tracemalloc.get_traced_memory()
print(f"当前内存使用: {current / 1024 / 1024:.2f} MB; 峰值: {peak / 1024 / 1024:.2f} MB")

tracemalloc.stop()

运行后你会看到两个数字:当前内存和峰值内存。如果某个函数在峰值时占了太多,那就得优化数据结构或清理引用了。

五、结合两者的监控类

如果你项目比较大,建议封装个监控工具类,方便全局使用:

import time
import psutil
import os

classMonitor:
def__init__(self):
        self.process = psutil.Process(os.getpid())

def__enter__(self):
        self.start_time = time.perf_counter()
        self.start_mem = self.process.memory_info().rss
return self

def__exit__(self, *args):
        end_time = time.perf_counter()
        end_mem = self.process.memory_info().rss
        print(f"耗时: {(end_time - self.start_time)*1000:.2f} ms")
        print(f"内存变化: {(end_mem - self.start_mem)/1024/1024:.2f} MB")

defrun_task():
    x = [i ** 2for i in range(1000000)]
    sum(x)

with Monitor():
    run_task()

这样就能在任何代码块前后加个 with Monitor():,自动打印内存变化和耗时了。

六、实际场景:分析慢函数

假设你在处理日志文件,发现程序跑得特别慢。你可以像这样快速分析:

@time_it
defprocess_log():
with open("app.log", "r") as f:
        data = f.readlines()
    result = [line for line in data if"ERROR"in line]
return result

process_log()

输出的执行时间能帮你判断瓶颈是不是在 I/O 上。如果是 CPU 密集型的,可以考虑多线程或异步。

七、总结一下

  • 只想看函数耗时:time.perf_counter() + 装饰器
  • 想看内存变化:psutil.Process().memory_info()
  • 想知道内存哪行吃得多:tracemalloc
  • 想统一监控:封装成类或上下文管理器

这几招结合起来,足够覆盖 90% 的性能排查场景了。别忘了,性能优化的第一步永远是——先量化问题,再动刀。

如果你想进一步分析全局性能,也可以用 cProfile:

import cProfile

defheavy_task():
for _ in range(5):
        [i ** 2for i in range(100000)]

cProfile.run('heavy_task()')

它能打印出每个函数调用的次数和平均耗时,非常适合定位复杂程序的瓶颈。

这样一来,你的 Python 项目在上线前就能“体检”一次:哪些函数太慢,哪里占内存太多,一清二楚。写代码不是怕有 bug,怕的是连 bug 吃内存都没察觉。

-END-

我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html

🔥虎哥私藏精品🔥

虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB,点击下方公众号回复关键字 python 全部免费领