web-dev-qa-db-fra.com

Mémoire totale utilisée par le processus Python?

Existe-t-il un moyen pour un programme Python de déterminer la quantité de mémoire qu'il utilise actuellement? J'ai assisté à des discussions sur l'utilisation de la mémoire pour un seul objet, mais ce dont j'ai besoin, c'est de l'utilisation totale de la mémoire pour le processus, afin de pouvoir déterminer quand il est nécessaire de commencer à supprimer les données en cache.

208
rwallace

Here est une solution utile qui fonctionne pour différents systèmes d'exploitation, notamment Linux, Windows 7, etc.:

import os
import psutil
process = psutil.Process(os.getpid())
print(process.memory_info().rss)  # in bytes 

Sur mon Python 2.7 actuel avec psutil 5.6.3, la dernière ligne doit être

print(process.memory_info()[0])

au lieu de cela (il y avait un changement dans l'API).

Remarque: faites pip install psutil s'il n'est pas encore installé.

243
Basj

Pour les systèmes Unix (Linux, Mac OS X, Solaris), vous pouvez utiliser la fonction getrusage() à partir du module de bibliothèque standard resource . L'objet résultant a l'attribut ru_maxrss, qui donne l'utilisation de la mémoire de pointe pour le processus appelant:

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

Les documents Python ne notent pas les unités. Reportez-vous à la page man getrusage.2 de votre système pour vérifier la valeur de l'unité. Sur Ubuntu 18.04, l’unité est notée en kilo-octets. Sur Mac OS X, ce sont des octets.

La fonction getrusage() peut également recevoir resource.RUSAGE_CHILDREN pour obtenir l'utilisation des processus enfants et (sur certains systèmes) resource.RUSAGE_BOTH pour l'utilisation totale des processus (auto et enfant).

Si vous ne vous souciez que de Linux, vous pouvez également lire le fichier /proc/self/status ou /proc/self/statm comme décrit dans les autres réponses à cette question et ceci un aussi.

181
Nathan Craike

Sous Windows, vous pouvez utiliser WMI ( page d'accueil , 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)

Sous Linux (à partir de 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
63
codeape

Sous unix, vous pouvez utiliser l'outil ps pour le surveiller:

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

où 1347 est un identifiant de processus. En outre, le résultat est en Mo.

29
bayer

J'aime it , merci pour @bayer. Je reçois un outil de comptage de processus spécifique, maintenant.

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

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

Joignez ma liste de processus.

$ ps aux  | grep python
root       943  0.0  0.1  53252  9524 ?        Ss   Aug19  52:01 /usr/bin/python /usr/local/bin/beaver -c /etc/beaver/beaver.conf -l /var/log/beaver.log -P /var/run/beaver.pid
root       950  0.6  0.4 299680 34220 ?        Sl   Aug19 568:52 /usr/bin/python /usr/local/bin/beaver -c /etc/beaver/beaver.conf -l /var/log/beaver.log -P /var/run/beaver.pid
root      3803  0.2  0.4 315692 36576 ?        S    12:43   0:54 /usr/bin/python /usr/local/bin/beaver -c /etc/beaver/beaver.conf -l /var/log/beaver.log -P /var/run/beaver.pid
jonny    23325  0.0  0.1  47460  9076 pts/0    S+   17:40   0:00 python
jonny    24651  0.0  0.0  13076   924 pts/4    S+   18:06   0:00 grep python

Référence

4
Chu-Siang Lai
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'])
3
Pedro Reis

Encore plus facile à utiliser que /proc/self/status: /proc/self/statm. C'est juste une liste délimitée par des espaces de plusieurs statistiques . Je n'ai pas été en mesure de dire si les deux fichiers sont toujours présents.

/ proc/[pid]/statm

Fournit des informations sur l'utilisation de la mémoire, mesurée en pages. Les colonnes sont:

  • taille (1) taille totale du programme (identique à VmSize dans/proc/[pid]/status)
  • resident (2) resident set size (identique à VmRSS dans/proc/[pid]/status)
  • shared (3) nombre de pages partagées résidentes (c'est-à-dire, sauvegardées par un fichier) (identique à RssFile + RssShmem dans/proc/[pid]/status)
  • text (4) text (code)
  • bibliothèque lib (5) (inutilisée depuis Linux 2.6; toujours 0)
  • data (6) data + stack
  • dt (7) pages altérées (inutilisées depuis Linux 2.6; toujours 0)

Voici un exemple simple:

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)

Cela produit une liste qui ressemble à ceci:

0
0
368640
368640
368640
638976
638976
909312
909312
909312

Vous pouvez constater qu’il saute d’environ 300 000 octets après environ 3 attributions de 100 000 octets.

3
Don Kirkby

Utilisation actuelle de la mémoire du processus en cours sous Linux, pour Python 2, Python 3 et pypy, sans aucune importation:

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())

Testé sur Linux 4.4 et 4.9, mais même une version antérieure de Linux devrait fonctionner.

La recherche dans man proc et la recherche d'informations sur le fichier /proc/$PID/status mentionnent les versions minimales de certains champs (comme Linux 2.6.10 pour "VmPTE"), mais le champ "VmRSS" (que j'utilise). ici) n'a pas une telle mention. Par conséquent, je suppose que cela existe depuis la première version.

3
Luc

Pour Python 3.6 et psutil 5.4.5, il est plus facile d'utiliser la fonction memory_percent() listée ici .

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

Ci-dessous, mon décorateur de fonctions, qui permet de suivre la quantité de mémoire utilisée par ce processus avant l'appel de fonction, la quantité de mémoire utilisée par celui-ci après l'appel de fonction et la durée d'exécution de la fonction.

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

Donc, quand vous avez une fonction décorée avec elle

from utils import track

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

Vous pourrez voir cette sortie:

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

Utiliser sh et os pour entrer dans la réponse de python bayer.

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

La réponse est en mégaoctets.

1
Newmu

Pour les systèmes Unix, la commande time (/ usr/bin/time) vous donne ces informations si vous passez -v. Voir Maximum resident set size ci-dessous, qui est le maximum (pic) réel (non virtuel) mémoire utilisée pendant l'exécution du programme:

$ /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
1
Charly Empereur-mot