파이썬 프로세스에서 사용하는 총 메모리?


266

파이썬 프로그램이 현재 사용중인 메모리 양을 결정할 수있는 방법이 있습니까? 단일 객체의 메모리 사용량에 대한 토론을 보았지만 필요한 것은 프로세스의 총 메모리 사용량이므로 캐시 된 데이터를 폐기 해야하는 시점을 결정할 수 있습니다.

답변:


303

다음 은 Linux, Windows 7 등 다양한 운영 체제에서 작동하는 유용한 솔루션입니다.

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

psutil 5.6.3으로 현재 Python 2.7 설치에서 마지막 줄은

print(process.memory_info()[0])

대신 (API에 변경 사항이 있음).

참고 : pip install psutil아직 설치되지 않은 경우 수행 하십시오.


3
psutil크로스 플랫폼이며 ps명령 줄 도구 와 동일한 값을 반환 할 수 있습니다 . pythonhosted.org/psutil/#psutil.Process.memory_info
amos

1
"( psutil) 현재 지원하는 리눅스, 윈도우, OSX, FreeBSD의 썬 솔라리스 2.6에서 3.4 파이썬 버전과 32 비트와 64 비트 아키텍처"에서 문서
세실리아

2
이 숫자가 프로세스 탐색기의 숫자와 일치하지 않는 이유는 무엇입니까? psutil의 수는 항상 약 10 % 더 큰 것 같습니다.
wordsforthewise

39
psutil은 표준 라이브러리에 없습니다
grisaitis

12
의 최신 버전의 psutil경우 psutil.Process()와 같습니다 psutil.Process(os.getpid()). 입력해야 할 일이 적습니다.
rnorris

208

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)

파이썬 문서는 단위의 메모를하지 않습니다. 특정 시스템 man getrusage.2페이지를 참조하여 값을 확인하십시오. 우분투 18.04에서 단위는 킬로바이트로 표시됩니다. Mac OS X에서는 바이트입니다.

getrusage()기능은 resource.RUSAGE_CHILDREN하위 프로세스의 사용량을 가져오고 (일부 시스템에서는) resource.RUSAGE_BOTH전체 (자체 및 하위) 프로세스 사용량 을 얻기 위해 제공 될 수도 있습니다 .

당신은 단지 리눅스에 대한 관심이 경우 대안을 읽을 수 /proc/self/status또는 /proc/self/statm이 질문에 대한 다른 답변에 설명 된대로 파일 너무 하나.


2
알겠습니다 SO에 질문을 병합하는 프로세스가 있는지 확실하지 않았습니다. 중복 게시물은 부분적으로 질문에 대한 표준 라이브러리 솔루션이 있었으며 부분적으로 담당자에게 보여주었습니다. ;)이 답변을 삭제해야합니까?
Nathan Craike

6
Mac OS는 RSS를 바이트 단위로 반환하고 Linux는 RSS를 킬로바이트 단위로 반환합니다.
Neil

13
단위는 킬로바이트가 아닙니다. 플랫폼에 따라 다르므로 resource.getpagesize ()를 사용해야합니다. 주어진 파이썬 문서 ( docs.python.org/2/library/resource.html#resource-usage )는 실제로 매우 명확합니다. 내 상자에 4096입니다.
Ben Lin

5
@BenLin 그 파이썬 문서는 분명히 잘못되었거나 Mac 버전에 버그가 있습니다. getrusage에 의해 사용되는 단위와 getpagesize에 의해 반환되는 값은 확실히 다릅니다.
Andrew

6
질문은 현재 사용법을 물었습니다 . 이 유의 최대 사용. (실수로 복사하여 붙여 넣는 사람들에게 경고하는 유용한 답변이 있습니다.)
Luc

65

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

14
Windows 코드가 작동하지 않습니다. 이 변경 사항은 다음과 같습니다.return int(result[0].WorkingSet)
John Fouhy

1
이 Windows 코드는 John Fouhy의 주석 수정 후에도 Windows 7 x64에서 작동하지 않습니다.
Basj

이 오류가 발생했습니다 : self._raw_query (wql)의 obj에 대한 [ wmi_object (obj, instance_of, fields)] 파일 "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) 누군가 나를 도울 수 있다면? 나는 x32에서 8 x64를 얻었지만 파이썬은
Radu Vlad

참고 : wmi 모듈의 (최신) 소스를 검사 한 후 John Fouhy의 제안에 따라 Windows 예제를 업데이트했습니다. (1) , (2) 도 참조하십시오 .
jedwards

33

유닉스에서는 ps도구를 사용하여 모니터링 할 수 있습니다 .

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

여기서 1347은 일부 프로세스 ID입니다. 또한 결과는 MB입니다.


8

가져 오기없이 Linux 에서 Python 2 , Python 3pypy 에 대한 현재 프로세스의 현재 메모리 사용량 :

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 값을 분리) 마지막으로 공백과 단위 (kB) 인 마지막 3 바이트를 차단합니다.
반환하려면 공백을 제거하고 숫자로 반환합니다.

Linux 4.4 및 4.9에서 테스트되었지만 초기 Linux 버전에서도 작동합니다. 파일 man proc에서 정보를 찾고 검색하는 경우 /proc/$PID/status일부 필드 (예 : "VmPTE"의 경우 Linux 2.6.10)의 최소 버전은 언급하지만 "VmRSS "(여기에서 사용하는) 필드에는 그러한 언급이 없습니다. 따라서 초기 버전 이후로 존재한다고 가정합니다.


5

내가 좋아하는 그것을 , @bayer 주셔서 감사합니다. 이제 특정 프로세스 수 도구를 얻습니다.

# 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

내 프로세스 목록을 첨부하십시오.

$ 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

참고


코드의 단지 최적화 멀티 파이프 피하기 위해ps aux | awk '/python/{sum+=$6}; END {print sum/1024 " MB"}'
NeronLeVelu

4

Python 3.6 및 psutil 5.4.5의 경우 여기에memory_percent() 나열된 함수 를 사용하는 것이 더 쉽습니다 .

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

1
이것은 lib psutil이 필요합니다
confiq

4

/proc/self/status: 보다 사용하기 쉽습니다 /proc/self/statm. 공백으로 구분 된 여러 통계 목록입니다 . 두 파일이 항상 존재하는지 알 수 없었습니다.

/ proc / [pid] / statm

메모리 사용량에 대한 정보를 페이지 단위로 제공합니다. 열은 다음과 같습니다.

  • 크기 (1) 총 프로그램 크기 (/ proc / [pid] / status의 VmSize와 동일)
  • 상주 (2) 상주 세트 크기 (/ proc / [pid] / 상태의 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

대략 10 만 바이트를 3 번 ​​할당 한 후 약 300,000 바이트 씩 점프 함을 알 수 있습니다.


4

아래는 함수 호출 전에이 프로세스가 소비 한 메모리 양, 함수 호출 후 사용하는 메모리 양 및 함수 실행 시간을 추적 할 수있는 함수 데코레이터입니다.

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

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

7
이것은 기능과 작동 방식에 대한 설명으로 개선 될 수 있습니다.
ArtOfWarfare

2
반환 된 큰 숫자 (8 자리)와 내가 아무것도하지 않는 방법에 따라 바이트 수 여야한다고 생각합니다. 따라서 유휴 대화 형 인스턴스의 경우 약 28.5MB입니다. (와우 ... 나는 위의 의견이 4 년 전의 내 것이라는 것을 알지 못했습니다 ... 이상합니다.)
ArtOfWarfare

3

유닉스 시스템의 경우 명령 time(/ usr / bin / time)은 -v를 전달하면 해당 정보를 제공합니다. 프로그램 실행 중 사용 된 최대 (피크) 실제 (가상이 아닌) 메모리 인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

1
time대신에 사용하려고하면 실패 할 수 있습니다 /usr/bin/time. 참조 : askubuntu.com/questions/434289/…
인수 됨

1

sh와 os를 사용하여 파이썬 바이어의 대답에 도달하십시오.

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

답은 메가 바이트입니다.


4
`sh '는 stdlib 모듈이 아닙니다. 그래도 pip로 설치할 수 있습니다.
Jürgen A. Erhard
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.