2013-05-02 12 views
17

matplotlibでFigureを作成する標準的な方法は、私がPythonで期待するように動作しないようです。デフォルトでは、ループ内でfig = matplotlib.figure()を呼び出すと、最終的にメモリ不足になります。参照カウントされた図を作成する

があります回避策に対処quiteafewの記事ですが、matplotlib.pyplot.close(fig)に明示的な呼び出しを必要とするのは少しハックようです。私が望むのは、fig参照を数えさせる簡単な方法です。そのため、メモリリークについて心配する必要はありません。これを行うにはいくつかの方法がありますか?

+1

これは、手動でのメモリ管理によく似ています。この場合、figureはWindowingシステムの外部リソース(ファイル記述子のようなもの)で、 'plt.figure()'はコンストラクタです。 'plt.close fig) 'はデストラクタです。 'clf'や' cla'などのために多くの破壊レベルがありますが。この場合、適切な方法は 'with 'ブラケットイディオム(" context manager ")を使うことです。 – CMCDragonkai

答えて

18

plt.figureを使用せずにFigureを作成する場合は、期待どおりに参照カウントする必要があります。例えば、(これは、同様に、非対話型AGGバックエンドを使用しています。)

from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas 
from matplotlib.figure import Figure 

# The pylab figure manager will be bypassed in this instance. 
# This means that `fig` will be garbage collected as you'd expect. 
fig = Figure() 
canvas = FigureCanvas(fig) 
ax = fig.add_subplot(111) 
+2

'FigureCanvas(fig)'がなければ、図を保存しようとすると例外が発生します。私は 'Figure'は常に' FigureCanvas'で描かれなければならないと思いますか? – Shep

+2

ねえ!それ以外の場合は何も描画できません(アーティストが作成されますが、プロットを保存/表示するまで描画は行われません)。 APIの疣贅です。理想的にはキャンバスは図と共に開始されるでしょう。 'fig.savefig(ファイル名)'の代わりに 'canvas.print_figure(ファイル名)'を使うと意味があります。それは純粋にあなたの理解のためです(キャンバスは描画/保存を扱うバックエンド固有の部分です)。最終的な結果は同じです。 –

+1

ええと、保存する前にキャンバスは全く存在しなければなりませんか? 'FigureCanvas(fig).print_figure(filename)'が1行の印刷機能として機能するかどうかは疑問です。 – Shep

2

をあなただけに使用することができ、数値を保存するのではなく、それらを表示するつもりなら:

def savefig(*args, **kwargs): 
    plt.savefig(*args, **kwargs) 
    plt.close(plt.gcf()) 

これは間違いなく、それほどハッキーではありませんが、何でも。

+0

ありがとう、これは図を保存して閉じる方法を教えてくれますが、質問には答えません。「C++でスマートポインタを使うにはどうすればよいですか?」と「生ポインタを割り当ててからdeleteあなたがそれを済ませたら "。 – Shep

+0

これは公正で、単に標準の 'plt' APIを使っている「メモリリークをどうやって心配することはできませんか?」という別の解決策を提案するだけです。 –

関連する問題