Python でのメモリ リーク
メモリ リークは、デバッグと修正が困難な一般的なプログラミングの問題です。
この記事では、小規模および大規模なサンプル プログラムを使用して Python のメモリ リークを調べます。 メモリ リークの原因を特定する方法と、それを修正する方法について説明します。
Python でのメモリ リーク
この記事では、Python メモリ管理システムの内部については説明しません。 しかし、Python メモリ システムの仕組みに興味がある場合は、Python の標準ライブラリのソース コードや他の高級プログラミング言語のコードを参照できます。
それでは、Python でのメモリ リークを調査するために例で使用するいくつかのライブラリについて説明しましょう。 最初のライブラリは Requests ライブラリで、特定の URL に対して HTTP リクエストを行うことができます。
REST API であろうと Web スクレイピングであろうと、これらのテクノロジーを先に進める前に、リクエストを学習する必要があります。 リクエストが URL に送信されると、レスポンスが返されます。
Python アプリケーションには、要求と応答の両方に対する組み込みの管理機能が含まれています。
次のコマンドを使用して簡単にインストールできます。
pip install requests
requests
ライブラリをインストールしたら、GC モジュールをインストールします。 これにより、Python ガベージ コレクターにアクセスできるようになります。
コレクターのアクティブ化、コレクターの無効化、収集頻度の調整、デバッグなどのオプションがあります。
C や C++ などの低レベル言語では、プログラマは使用されなくなったリソースを手動で解放する必要があります。 別の言い方をすれば、リソースを管理するためのプログラミングを開発します。
ただし、Python や Java などの高水準言語には、自動化されたメモリ管理であるゴミ収集の概念が含まれています。 ごみ収集は、プログラムのメモリの割り当てと解放を担当します。
使用する GC モジュールのメソッドは get_object()
です。これは、ごみ箱コレクションから追跡対象のオブジェクトを提供するメソッドです。 また、collect()
メソッドを使用して、コレクターが制御するリストから解放された非参照オブジェクトを提供します。
Python でメモリ リークを特定する
ここで、プログラムの実行中にメモリ リークが発生したかどうかを特定する方法について説明します。 例から始めて、上記のライブラリを使用してリークがあったかどうかを確認しましょう。
最初に、この例で前述したライブラリをインポートします。
# python
import requests
import gc
次に、Requests ライブラリを使用して google.com
からの応答を要求し、受け取ったステータス コードを返す関数 getGoogle()
を定義します。
コード:
# python
def getGoogle():
resultGot = requests.get("https://google.com")
print("Status Code recieved is ", resultGot.status_code)
return
ここで、別の関数 checkMemoryLeak()
を定義します。この関数では、関数 getGoogle()
を呼び出す前後にガベージ オブジェクトを収集します。
コード:
# python
def checkMemoryLeak():
print("Memory Leaked before calling getGoogle()")
print(len(gc.get_objects()))
getGoogle()
print("Memory Leaked before calling getGoogle()")
print(len(gc.get_objects()))
checkMemoryLeak()
出力:
例でわかるように、関数を呼び出す前のガベージ コレクターの長さは 17472 でしたが、関数を呼び出した後、長さは 17698 に増加しました。これは、いくつかのタスクを実行するときに常にメモリ リークがあることを示しています。
ここで、メモリ リークを修正し、メモリ リークなしでできるだけ多くのデータを収集する方法について説明します。
Python のメモリ リークを修正
関数 gc.collect()
を使用して Python のメモリ リークを修正できます。 同じプログラムを使用しますが、メモリ リークが発生しないか最小限になるように修正します。
この例では、関数 getGoogle()
を呼び出した後、gc.collect()
を直接呼び出します。これにより、メモリ リークが減少し、問題が修正されます。
コード:
# python
import requests
import gc
def getGoogle():
resultGot = requests.get("https://google.com")
print("Status Code recieved is ", resultGot.status_code)
def checkMemoryLeak():
print("Memory Leaked before calling getGoogle()")
print(len(gc.get_objects()))
getGoogle()
gc.collect()
print("Memory Leaked before calling getGoogle()")
print(len(gc.get_objects()))
checkMemoryLeak()
出力:
例でわかるように、gc.collect()
を使用した後、メモリ リークの数が減少します。 このようにして、関数呼び出し中のメモリ リークを防ぐことができます。
Rana is a computer science graduate passionate about helping people to build and diagnose scalable web application problems and problems developers face across the full-stack.
LinkedIn