開発環境では、通常、Pythonプログラムを作成するときにメモリの問題に注意を払うことはめったにありません。cやc ++を作成する友人はこの問題をもっと検討するかもしれませんが、Pythonプログラムにメモリリークの問題が発生すると、非常に面倒になります。それでは、この種の問題をどのように回避する必要がありますか、それが発生した場合、それを解決する方法を見てみましょう!
起因
メモリリークとは、プログラムが過失またはエラーのために使用されなくなったメモリを解放できない状況を指します。メモリリークは、メモリの物理的な消失を意味するものではありませんが、アプリケーションがメモリの特定のセグメントを割り当てた後、設計エラーのために、メモリのこのセグメントの制御を失い、メモリの浪費を引き起こします。プログラムの速度が低下したり、システムがクラッシュしたりするなどの重大な結果。del()関数を使用したオブジェクト間の循環参照は、メモリリークの主な原因です。
プログラム
オブジェクトを使用しない場合は、:delobjectを使用してオブジェクトの参照カウントを削除し、メモリリークを効果的に防止します。Python拡張モジュールgcを使用して、リサイクルできないオブジェクトに関する詳細情報を表示します。sys.getrefcount(obj)を介してオブジェクトの参照カウントを取得し、戻り値が0であるかどうかに基づいてメモリリークが発生しているかどうかを判断できます。
ただし、gcのガベージコレクションメカニズムにより、ガベージコレクターによって管理されるすべてのPythonオブジェクト(ガベージオブジェクトと非ガベージオブジェクトを含む)をトラバースする必要があります。このプロセスには時間がかかり、プログラムがフリーズする可能性があります。メモリとCPUの要件。シナリオはパフォーマンスに影響を与えます。では、どうすればメモリリークをエレガントに回避できるでしょうか。
安全なコードを書く
たとえば、以下にメモリリークがあるcycle_ref関数の場合、関数が終了する前に循環参照を削除すると、メモリリークの問題を解決できます。
def cycle_ref():
a1 = A()
a2 = A()
a1.child = a2
a2.child = a1
# 解除循环引用,避免内存泄露
a1.child = None
a2.child = None
しかし、上記の方法では、無関係なコードの1行または2行を忘れて、壊滅的な結果を引き起こす可能性があります。結局のところ、トラには昼寝もあります。それではどうしますか?心配しないでください。Pythonはすでにこれを考慮しています。弱い参照です。
弱い参照
Python標準ライブラリはweakrefモジュールを提供します。弱い参照は参照カウントにカウントされません。主な目的は循環参照を解決することです。listやdictなど、すべてのオブジェクトがweakrefをサポートしているわけではありません。以下は、weakrefのより一般的に使用される方法です。
"" "
- class weakref.ref(object [、callback]):弱参照オブジェクトを作成します。objectは参照オブジェクト、callbackはコールバック関数です(参照オブジェクトが削除されると、コールバック関数が呼び出されます)
2. weakref.proxy(object [、callback]):上記と同じパラメーターを使用して、弱参照で実装されたプロキシオブジェクトを作成します
3.weakref.getweakrefcount(object):オブジェクトオブジェクトに関連付けられている弱く参照されているオブジェクトの数を取得します
4.weakref.getweakrefs(object):オブジェクトに関連付けられた弱参照オブジェクトのリストを取得します
5.class weakref.WeakKeyDictionary([dict]):キーが弱参照オブジェクトである辞書を作成します
6.class weakref.WeakValueDictionary([dict]):値が弱参照オブジェクトである辞書を作成します
7.class weakref.WeakSet([elements]):メンバーが弱参照オブジェクトであるコレクションオブジェクトを作成します
"" "
同様に、上記でメモリリークが発生したcycle_ref関数の場合、weakrefを使用してわずかに変更すると、メモリリークの問題をより安全に解決できます。
インポートweakref
クラスA(オブジェクト):
def __init__(self):
self.data = [x for x in range(100000)]
self.child = None
def __del__(self):
pass
def cycle_ref():
a1 = A()
a2 = A()
a1.child = weakref.proxy(a2)
a2.child = weakref.proxy(a1)
名前の場合== 'メイン':
import time
while True:
time.sleep(0.5)
cycle_ref()