Python中确定可用的RAM

19

我希望我的Python脚本能够使用所有可用的空闲内存,但不超过此限制(出于效率原因)。为了正确控制这一点,我可以通过仅读取有限数量的数据来实现,但我需要知道运行时有多少可用的空闲内存。它将在多个Linux系统上运行。有可能在运行时确定可用的空闲内存吗?

5个回答

24

在Linux系统中,我偶尔会使用以下命令:

def memory():
    """
    Get node total memory and memory usage
    """
    with open('/proc/meminfo', 'r') as mem:
        ret = {}
        tmp = 0
        for i in mem:
            sline = i.split()
            if str(sline[0]) == 'MemTotal:':
                ret['total'] = int(sline[1])
            elif str(sline[0]) in ('MemFree:', 'Buffers:', 'Cached:'):
                tmp += int(sline[1])
        ret['free'] = tmp
        ret['used'] = int(ret['total']) - int(ret['free'])
    return ret

当脚本启动时,可以运行此操作。在忙碌的系统上,RAM通常会被频繁使用和释放,因此在决定使用多少RAM之前,应考虑这一点。此外,大多数Linux系统的swappiness值为60。在使用内存时,最不经常使用的页面将被交换出去。您可能会发现自己使用SWAP而不是RAM。

希望这有所帮助。


一个 swappiness 值为 60 表示什么? - marshall
@marshall http://askubuntu.com/questions/103915/how-do-i-configure-swappiness 给出了一个公正的解释。 - nic
这是内核交换页面的可能性。值的范围从0到100,其中0最不可能交换(通常这样做是为了避免内存不足的情况),而100则是积极交换。 - Gabriel Samfira

10

另一个选项是Python包psutil

stats = psutil.virtual_memory()  # returns a named tuple
available = getattr(stats, 'available')
print(available)
根据文档available字段"是通过对不同平台上的不同内存值求和计算得出的,应该用于以跨平台的方式监视实际内存使用情况。"

请注意返回值将以字节为单位。

2
这是Python的内置包吗? - vdi
2
psutil 不是内置的包;相反,您必须先执行 pip install psutil 安装它。 - Wolf

7

你可以直接阅读/proc/meminfo文件。请注意,“可用内存”通常很低,因为操作系统会将未使用的内存用于缓存。

此外,最好不要试图超越操作系统的内存管理。这通常只会导致程序变慢(或者更糟)。最好只使用你需要的内存。如果要在具有先前未知内存量的计算机上使用尽可能多的内存,我建议先检查已安装的内存量(/proc/meminfo中的MemTotal),留下一定数量的内存给操作系统和作为安全余量(比如说1 GB),然后使用剩余的内存。


1
有些*nix系统没有/proc目录 :( - nic
2
@nic /proc/meminfo与其当前设置的值至少从Linux 2.6开始就已经可用了。这应该足够长时间了。 - Carsten
1
除了Linux之外,还有其他*nix系统,因此为了通用性,这值得一提。 - nic
1
没错。也许我们可以把我的评论视为一种有趣的珍品,让感兴趣的读者来欣赏呢? :) - nic
1
我认为你应该比操作系统内存管理更聪明,因为你知道如何将处理分成块,并且你更清楚哪些东西将来会被使用。一个依赖于交换空间的numpy算法将比一个适当大小的块编写的算法慢得多,对吧? - endolith
显示剩余9条评论

5

因为原始发帖者编写的代码需要在多种Linux系统上运行,所以我在这里发布了一个面向对象的解决方案来查询Linux内存。 psutil是一个很棒的库,但如果由于某些原因无法安装它,则可以简单地使用以下解决方案:

示例用法:

>>> f = FreeMemLinux()
>>> print f.total, f.used,  f.user_free
8029212 3765960 4464816
>>>
>>> f_mb = FreeMemLinux(unit='MB')
>>> print f_mb.total, f_mb.used,  f_mb.user_free
7841.02734375 3677.6953125 4360.171875
>>>
>>> f_percent = FreeMemLinux(unit='%')
>>> print f_percent.total, f_percent.used, f_percent.user_free
100.0 46.9032328453 55.60715049

代码:

class FreeMemLinux(object):
    """
    Non-cross platform way to get free memory on Linux. Note that this code
    uses the `with ... as`, which is conditionally Python 2.5 compatible!
    If for some reason you still have Python 2.5 on your system add in the
head of your code, before all imports:
    from __future__ import with_statement
    """

    def __init__(self, unit='kB'):

        with open('/proc/meminfo', 'r') as mem:
            lines = mem.readlines()

        self._tot = int(lines[0].split()[1])
        self._free = int(lines[1].split()[1])
        self._buff = int(lines[2].split()[1])
        self._cached = int(lines[3].split()[1])
        self._shared = int(lines[20].split()[1])
        self._swapt = int(lines[14].split()[1])
        self._swapf = int(lines[15].split()[1])
        self._swapu = self._swapt - self._swapf

        self.unit = unit
        self._convert = self._factor()

    def _factor(self):
        """determine the convertion factor"""
        if self.unit == 'kB':
            return 1
        if self.unit == 'k':
            return 1024.0
        if self.unit == 'MB':
            return 1/1024.0
        if self.unit == 'GB':
            return 1/1024.0/1024.0
        if self.unit == '%':
            return 1.0/self._tot
        else:
            raise Exception("Unit not understood")

    @property
    def total(self):
        return self._convert * self._tot

    @property
    def used(self):
        return self._convert * (self._tot - self._free)

    @property
    def used_real(self):
        """memory used which is not cache or buffers"""
        return self._convert * (self._tot - self._free -
                                self._buff - self._cached)

    @property
    def shared(self):
        return self._convert * (self._tot - self._free)

    @property
    def buffers(self):
        return self._convert * (self._buff)

    @property
    def cached(self):
        return self._convert * self._cached

    @property
    def user_free(self):
        """This is the free memory available for the user"""
        return self._convert *(self._free + self._buff + self._cached)

    @property
    def swap(self):
        return self._convert * self._swapt

    @property
    def swap_free(self):
        return self._convert * self._swapf

    @property
    def swap_used(self):
        return self._convert * self._swapu

请注意,这个翻译可能不准确,因为在我的Ubuntu 18.04系统上,/proc/meminfo文件中的行位置是不同的。例如,line[1]是MemFree,但在我的系统中,line[2]是MemAvailable,而不是Buffers(在我的系统上是line[3])。 - Cardin

1
我想你可以使用免费的http://www.cyberciti.biz/faq/linux-check-memory-usage/,也可以使用ps或者SO-thread底部发布的MemoryMonitor类来完成这个任务。请留出一些未使用的内存给其他可能急需它的进程,以避免代表它们进行磁盘写入。如果你使用free或ps,你需要解析输出,但这不应该很难。记住,你需要实时分析可用的内存,这样你就可以在另一个进程由于某种原因变得占用内存时进行调整。
另外,请参阅此线程:如何在Python中获取当前CPU和RAM使用情况?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接