[python] 파이썬 메모리 누수 [폐쇄]

충분히 오래 실행하면 시스템의 모든 메모리를 사용하는 장기 실행 스크립트가 있습니다.

스크립트에 대한 자세한 내용을 다루지 않고 두 가지 질문이 있습니다.

  1. 준수해야 할 “모범 사례”가 있습니까?
  2. 파이썬에서 메모리 누수를 디버깅하는 기술은 무엇입니까?


답변

이 기사를 살펴보십시오 : 파이썬 메모리 누수 추적

또한 가비지 수집 모듈에는 실제로 디버그 플래그가 설정 될 수 있습니다. 상기 봐 set_debug기능. 또한, 호출 후 생성 된 객체의 유형을 결정하기 위해 Gnibbler의이 코드를 살펴보십시오 .


답변

이전에 언급 한 대부분의 옵션을 시도했지만이 작고 직관적 인 패키지가 가장 좋습니다 : pympler

가비지 수집되지 않은 객체를 추적하는 것은 매우 간단합니다.이 작은 예를 확인하십시오.

통해 패키지를 설치 pip install pympler

from pympler.tracker import SummaryTracker
tracker = SummaryTracker()

# ... some code you want to investigate ...

tracker.print_diff()

출력에는 추가 된 모든 개체와 소비 한 메모리가 표시됩니다.

샘플 출력 :

                                 types |   # objects |   total size
====================================== | =========== | ============
                                  list |        1095 |    160.78 KB
                                   str |        1093 |     66.33 KB
                                   int |         120 |      2.81 KB
                                  dict |           3 |       840 B
      frame (codename: create_summary) |           1 |       560 B
          frame (codename: print_diff) |           1 |       480 B

이 패키지는 더 많은 기능을 제공합니다. 확인 pympler의 문서는 , 특히 섹션은 메모리 누수를 확인 .


답변

내가 만든 mem_top 도구를 추천하겠습니다

비슷한 문제를 해결하는 데 도움이되었습니다.

파이썬 프로그램에서 메모리 누수의 주요 용의자를 즉시 ​​보여줍니다.


답변

Tracemalloc 모듈 은 Python 3.4부터 내장 모듈 로 통합되었으며 이전 버전의 Python에서도 타사 라이브러리 로 사용할 수 있습니다 (테스트하지는 않았습니다).

이 모듈은 가장 많은 메모리를 할당 한 정확한 파일과 라인을 출력 할 수 있습니다. IMHO,이 정보는 각 유형에 할당 된 인스턴스 수보다 무한히 가치가 있습니다 (99 %의 많은 튜플이 생겨 단서이지만 대부분의 경우 거의 도움이되지 않습니다).

pyrasite와 함께 tracemalloc 을 사용하는 것이 좋습니다 . 10 회 중 9 회 , 피라 사이트 쉘 에서 상위 10 개 스 니펫 을 실행하면 10 분 내에 누출을 해결할 수있는 충분한 정보와 힌트가 제공됩니다. 그러나 누출 원인을 여전히 찾을 수 없다면이 스레드에서 언급 한 다른 도구와 함께 pyrasite-shell이 ​​힌트를 줄 것입니다. 또한 pyrasite에서 제공하는 모든 추가 도우미 (예 : 메모리 뷰어)도 살펴 봐야합니다.


답변

전역 또는 정적 데이터 (장기 데이터)를 특별히 살펴 봐야합니다.

이 데이터가 제한없이 커지면 Python에서도 문제가 발생할 수 있습니다.

가비지 수집기는 더 이상 참조되지 않는 데이터 만 수집 할 수 있습니다. 그러나 정적 데이터는 해제해야하는 데이터 요소를 연결할 수 있습니다.

또 다른 문제는 메모리주기 일 수 있지만, 이론적으로 가비지 콜렉터는 최소한 수명이 긴 데이터에 연결되지 않는 한주기를 찾아서 제거해야합니다.

어떤 종류의 장수 데이터가 특별히 귀찮은가? 모든 목록과 사전을 잘 살펴보십시오. 제한없이 커질 수 있습니다. 사전에서는 dicts에 액세스 할 때 문제가 발생하지 않을 수도 있습니다. 사전의 키 수가 눈에 띄지 않을 수 있습니다 …


답변

프로덕션 환경과 같이 장기 실행 프로세스의 메모리 누수를 감지하고 찾으려면 이제 stackimpact를 사용할 수 있습니다 . 아래에 tracemalloc을 사용합니다 . 이 게시물에 더 많은 정보가 있습니다.

여기에 이미지 설명을 입력하십시오


답변

모범 사례에 이르기까지 재귀 함수를 주시하십시오. 제 경우에는 재귀 문제가 발생했습니다 (필요하지 않은 곳). 내가하고있는 일에 대한 간단한 예 :

def my_function():
    # lots of memory intensive operations
    # like operating on images or huge dictionaries and lists
    .....
    my_flag = True
    if my_flag:  # restart the function if a certain flag is true
        my_function()

def main():
    my_function()

이 재귀 방식으로 작동해도 가비지 수집이 트리거되지 않고 함수의 잔해가 제거되지 않으므로 메모리 사용을 통해 매번 증가하고 증가합니다.

내 해결책은 my_function ()에서 재귀 호출을 꺼내고 다시 호출 할 때 main () 처리하는 것입니다. 이런 식으로 함수가 자연스럽게 끝나고 자체적으로 정리됩니다.

def my_function():
    # lots of memory intensive operations
    # like operating on images or huge dictionaries and lists
    .....
    my_flag = True
    .....
    return my_flag

def main():
    result = my_function()
    if result:
        my_function()