是否有一种方法可以让Python程序确定它当前使用了多少内存?我看到过关于单个对象的内存使用情况的讨论,但我需要的是进程的总内存使用情况,这样我就可以确定何时需要开始丢弃缓存的数据。


当前回答

使用sh和os进入python拜耳的答案。

float(sh.awk(sh.ps('u','-p',os.getpid()),'{sum=sum+$6}; END {print sum/1024}'))

答案是以兆字节为单位。

其他回答

下面是我的函数装饰器,它可以跟踪这个进程在函数调用之前消耗了多少内存,在函数调用之后使用了多少内存,以及函数执行了多长时间。

import time
import os
import psutil


def elapsed_since(start):
    return time.strftime("%H:%M:%S", time.gmtime(time.time() - start))


def get_process_memory():
    process = psutil.Process(os.getpid())
    return process.memory_info().rss


def track(func):
    def wrapper(*args, **kwargs):
        mem_before = get_process_memory()
        start = time.time()
        result = func(*args, **kwargs)
        elapsed_time = elapsed_since(start)
        mem_after = get_process_memory()
        print("{}: memory before: {:,}, after: {:,}, consumed: {:,}; exec time: {}".format(
            func.__name__,
            mem_before, mem_after, mem_after - mem_before,
            elapsed_time))
        return result
    return wrapper

当你用它来装饰某个函数时

from utils import track

@track
def list_create(n):
    print("inside list create")
    return [1] * n

你将会看到这样的输出:

inside list create
list_create: memory before: 45,928,448, after: 46,211,072, consumed: 282,624; exec time: 00:00:00

对于Python 3.6和psutil 5.4.5,使用这里列出的memory_percent()函数更容易。

import os
import psutil
process = psutil.Process(os.getpid())
print(process.memory_percent())

在unix上,你可以使用ps工具来监视它:

$ ps u -p 1347 | awk '{sum=sum+$6}; END {print sum/1024}'

其中1347是某个进程id。同样,结果的单位是MB。

import os, win32api, win32con, win32process
han = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION|win32con.PROCESS_VM_READ, 0, os.getpid())
process_memory = int(win32process.GetProcessMemoryInfo(han)['WorkingSetSize'])

甚至比/proc/self/status更容易使用:/proc/self/statm.它只是一个由几个统计数据以空格分隔的列表。我无法判断这两个文件是否始终存在。

/proc/[pid]/statm Provides information about memory usage, measured in pages. The columns are: size (1) total program size (same as VmSize in /proc/[pid]/status) resident (2) resident set size (same as VmRSS in /proc/[pid]/status) shared (3) number of resident shared pages (i.e., backed by a file) (same as RssFile+RssShmem in /proc/[pid]/status) text (4) text (code) lib (5) library (unused since Linux 2.6; always 0) data (6) data + stack dt (7) dirty pages (unused since Linux 2.6; always 0)

这里有一个简单的例子:

from pathlib import Path
from resource import getpagesize

PAGESIZE = getpagesize()
PATH = Path('/proc/self/statm')


def get_resident_set_size() -> int:
    """Return the current resident set size in bytes."""
    # statm columns are: size resident shared text lib data dt
    statm = PATH.read_text()
    fields = statm.split()
    return int(fields[1]) * PAGESIZE


data = []
start_memory = get_resident_set_size()
for _ in range(10):
    data.append('X' * 100000)
    print(get_resident_set_size() - start_memory)

生成的列表如下所示:

0
0
368640
368640
368640
638976
638976
909312
909312
909312

你可以看到,在大约分配了3次10万字节后,它增加了大约30万字节。