Python程序是否可以确定当前正在使用多少内存?我已经看到了有关单个对象的内存使用情况的讨论,但是我需要的是该过程的总内存使用情况,以便可以确定何时需要开始丢弃缓存的数据。

#1 楼

以下是适用于各种操作系统(包括Linux,Windows等)的有用解决方案:
import os, psutil
process = psutil.Process(os.getpid())
print(process.memory_info().rss)  # in bytes 

对于Python 2.7和psutil 5.6.3,最后一行应为
print(process.memory_info()[0])

(而不是API进行了更改)。
注意:


如果尚未安装,请执行pip install psutil


方便实用的一线式工具,如果您想快速了解一下过程需要多少MB:
import os, psutil; print(psutil.Process(os.getpid()).memory_info().rss / 1024 ** 2)




评论


psutil是跨平台的,并且可以返回与ps命令行工具相同的值:pythonhosted.org/psutil/#psutil.Process.memory_info

–amos
2014年7月3日在21:38

为什么这个数字与流程浏览器中的数字不匹配? psutil中的数字似乎总是比大约大10%。

–明智的话
15年5月13日在22:42

请注意,psutil不在标准库中

–乳头炎
16年8月18日在19:11

对于最新版本的psutil,psutil.Process()等效于psutil.Process(os.getpid())。这是您需要记住的少一件事。

–rnorris
19年4月26日在3:07

为什么使用rss?在psutil文件中:rss |驻留集大小,vms |程序总大小。所以我认为最后一行应该是print(process.memory_info()。vms)

–哈利尔·伊布拉辛·奥伊马克(HalilİbrahimOymacı)
19-10-25在13:16

#2 楼

对于基于Unix的系统(Linux,Mac OS X,Solaris),可以使用标准库模块getrusage()中的resource函数。生成的对象具有属性ru_maxrss,该属性给出了调用进程的峰值内存使用量:

>>> resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
2656  # peak memory usage (kilobytes on Linux, bytes on OS X)


Python文档未记录单位。请参阅您特定系统的man getrusage.2页以检查单位的值。在Ubuntu 18.04上,单位记为千字节。在Mac OS X上,它是字节。

还可以给getrusage()函数resource.RUSAGE_CHILDREN来获取子进程的使用情况,(在某些系统上)给resource.RUSAGE_BOTH来获取(自身和子)进程的全部使用情况。 br />
如果您只关心Linux,则可以替代阅读/proc/self/status/proc/self/statm文件,如有关此问题的其他答案所述,也可以阅读此文件。

评论


好吧,会的。我不确定SO是否有合并问题的流程或什么。重复的帖子部分是为了向人们展示在两个问题上都有一个标准的图书馆解决方案……部分是针对销售代表的。 ;)我应该删除此答案吗?

–内森·克雷克(Nathan Craike)
2011-10-6 3:19



Mac OS绝对以字节为单位返回RSS,Linux以千字节为单位返回。

–尼尔
2013年12月6日23:33

单位不是千字节。它与平台有关,因此您必须使用resource.getpagesize()进行查找。给定的Python文档(docs.python.org/2/library/resource.html#resource-usage)实际上非常清楚。我的盒子里是4096。

–本林
2014年4月15日在16:53



@BenLin那些Python文档显然是错误的,或者Mac版本上存在错误。 getrusage使用的单位和getpagesize返回的值肯定是不同的。

–安德鲁(Andrew)
15年7月8日在17:56

该问题询问当前的用法。请注意,这是最大用法。 (这仍然是一个有用的答案,只是警告错误地将其粘贴粘贴的人。)

–吕克
18年1月23日在8:29

#3 楼

在Windows上,您可以使用WMI(主页,cheeseshop):


def memory():
    import os
    from wmi import WMI
    w = WMI('.')
    result = w.query("SELECT WorkingSet FROM Win32_PerfRawData_PerfProc_Process WHERE IDProcess=%d" % os.getpid())
    return int(result[0].WorkingSet)


在Linux上(来自python Cookbook http://code.activestate.com/recipes/286222) /:

import os
_proc_status = '/proc/%d/status' % os.getpid()

_scale = {'kB': 1024.0, 'mB': 1024.0*1024.0,
          'KB': 1024.0, 'MB': 1024.0*1024.0}

def _VmB(VmKey):
    '''Private.
    '''
    global _proc_status, _scale
     # get pseudo file  /proc/<pid>/status
    try:
        t = open(_proc_status)
        v = t.read()
        t.close()
    except:
        return 0.0  # non-Linux?
     # get VmKey line e.g. 'VmRSS:  9999  kB\n ...'
    i = v.index(VmKey)
    v = v[i:].split(None, 3)  # whitespace
    if len(v) < 3:
        return 0.0  # invalid format?
     # convert Vm value to bytes
    return float(v[1]) * _scale[v[2]]


def memory(since=0.0):
    '''Return memory usage in bytes.
    '''
    return _VmB('VmSize:') - since


def resident(since=0.0):
    '''Return resident memory usage in bytes.
    '''
    return _VmB('VmRSS:') - since


def stacksize(since=0.0):
    '''Return stack size in bytes.
    '''
    return _VmB('VmStk:') - since


评论


Windows代码对我不起作用。所做的更改是:返回int(result [0] .WorkingSet)

–约翰·富希(John Fouhy)
2010年8月31日0:46



即使修改了John Fouhy的注释,该Windows代码也不适用于Windows 7 x64。

–巴吉
2014年2月7日15:59

我有这个错误:在self._raw_query(wql)中为obj返回[wmi_object(obj,instance_of,字段)。]文件“ C:\ Python27 \ lib \ site-packages \ win32com \ client \ util.py”,第84行,在下一个返回_get_good_object_(self._iter.next(),resultCLSID = self.resultCLSID)pywintypes.com_error:(-2147217385,'OLE error 0x80041017',None,None)如果有人可以帮助我吗?我赢了8 x64,但在x32上使用了python

–拉杜·弗拉德(Radu Vlad)
2014年9月9日下午6:06

注意:在检查了wmi模块的(最新)源之后,我根据John Fouhy的建议更新了Windows示例。另请参阅(1),(2)。

– jedwards
16-3-17在16:24



@jedwards:在> 90%的情况下,WorkingSet是一个非常糟糕的数字。这只是当前在RAM中的那部分内存

–托马斯·韦勒(Thomas Weller)
7月16日20:26

#4 楼

在UNIX上,您可以使用ps工具对其进行监视:

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


其中1347是某个进程ID。此外,结果以MB为单位。

#5 楼

Linux,Python 2,Python 3和pypy上当前进程的当前内存使用情况,没有任何导入:
 def getCurrentMemoryUsage():
    ''' Memory usage in kB '''

    with open('/proc/self/status') as f:
        memusage = f.read().split('VmRSS:')[1].split('\n')[0][:-3]

    return int(memusage.strip())
 

它读取当前进程的状态文件,获取VmRSS:之后的所有内容,然后获取第一个换行符之前的所有内容(隔离VmRSS的值),最后剪切掉最后3个字节,即空格和单位(kB)。 br />要返回,它将剥离所有空格并将其作为数字返回。
在Linux 4.4和4.9上进行了测试,但即使是早期的Linux版本也可以使用:在man proc中查找并在/proc/$PID/status文件中搜索信息,它提到了某些字段的最低版本(例如“ VmPTE”的Linux 2.6.10),但是“ VmRSS”字段(我在这里使用)没有提及。因此,我认为它自早期版本以来就已经存在。

#6 楼

我喜欢它,谢谢@bayer。我现在有了特定的过程计数工具。

# Megabyte.
$ ps aux | grep python | awk '{sum=sum+}; END {print sum/1024 " MB"}'
87.9492 MB

# Byte.
$ ps aux | grep python | awk '{sum=sum+}; END {print sum " KB"}'
90064 KB


附上我的过程列表。


内存-Linux:找出正在使用所有RAM的进程是什么? -超级用户
Python进程使用的总内存是多少? -堆栈溢出
linux-ps aux输出含义-超级用户


评论


只是代码的优化,以避免多管道ps aux | awk'/ python / {sum + = $ 6}; END {打印总和/ 1024“ MB”}'

– NeronLeVelu
17-10-4在5:06



#7 楼

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

评论


这需要lib psutil

–confiq
5月23日10:41

#8 楼

/proc/self/status更容易使用:/proc/self/statm。这只是几个统计信息的以空格分隔的列表。我无法确定两个文件是否始终存在。


/ proc / [pid] / statm

提供有关已测量内存使用情况的信息
列为:


大小(1)程序总大小
(与/ proc / [pid] / status中的VmSize相同)
居民(2)居民集大小
(与/ proc / [pid] / status中的VmRSS相同)
共享(3)居民共享页数(即,由文件支持)
(与/ proc / [pid] / status中的RssFile + RssShmem相同)
文本(4)文本(代码)
lib(5)库(自Linux 2.6起未使用;始终为0)
数据(6)数据+堆栈
dt(7)脏页(自Linux 2.6起未使用;始终为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


你可以看到我在大约分配了100,000个字节的3次后,t跳了约300,000个字节。

#9 楼

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

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


#10 楼

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'])


评论


可以通过解释它的功能和工作方式来改进它。

–ArtOfWarfare
2014年11月25日15:39

基于返回的大量数字(8位数字)以及我什么都不做,我猜测这必须是字节?因此,一个相当空闲的交互式实例大约需要28.5 MB。 (哇...我什至都没有意识到以上评论是4年前的我了...这很奇怪。)

–ArtOfWarfare
18年6月8日在18:50

#11 楼

对于Unix系统,如果传递-v,则time(/ usr / bin / time)命令会为您提供该信息。请参阅下面的Maximum resident set size,它是程序执行期间使用的最大(峰值)实际(非虚拟)内存:

$ /usr/bin/time -v ls /

    Command being timed: "ls /"
    User time (seconds): 0.00
    System time (seconds): 0.01
    Percent of CPU this job got: 250%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.00
    Average shared text size (kbytes): 0
    Average unshared data size (kbytes): 0
    Average stack size (kbytes): 0
    Average total size (kbytes): 0
    Maximum resident set size (kbytes): 0
    Average resident set size (kbytes): 0
    Major (requiring I/O) page faults: 0
    Minor (reclaiming a frame) page faults: 315
    Voluntary context switches: 2
    Involuntary context switches: 0
    Swaps: 0
    File system inputs: 0
    File system outputs: 0
    Socket messages sent: 0
    Socket messages received: 0
    Signals delivered: 0
    Page size (bytes): 4096
    Exit status: 0


评论


请注意,如果您只是尝试使用时间而不是/ usr / bin / time,这可能会失败。参见:askubuntu.com/questions/434289/…

–购买
4月9日19:49

#12 楼

使用sh和os来了解python Bayer的答案。

评论


应该注意的是,“ sh”不是stdlib模块。它可以通过pip安装。

–于尔根·艾哈德(JürgenA. Erhard)
2013年9月4日0:00