nokの雑記

技術的な内容にしようと思ったけど無理でした。

matplotlibのfigureオブジェクトをpickleで再利用しようとしてハマった話

備忘録がてら……

tl;dr
pickle化するならfig.show()の前にやる.

参考 stackoverflow.com

やりたかったこと

matplotlibのfigオブジェクトをpickleでダンプする → あとで読み込んで再利用する
(一応plt.show()のウィンドウで拡大縮小できるし,軸いじったりしたいし)

やったこと&おきたこと

やったこと

(i)python3.5.2(Anaconda; win32)で試したコード

スクリプト1

import matplotlib.pyplot as plt
import pickle

fig = plt.figure()
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)

ax1.plot([1,2,3],[3,2,1])
ax2.plot([1,2,3],[1,2,3]) 

fig.show()

# あとで使うために保存
with open("./myfig.pkl", "wb") as f:
    pickle.dump(fig, f)

スクリプト2

import matplotlib.pyplot as plt
import pickle

# スクリプト1で保存したものを読み込み
with open("./myfig.pkl", "rb") as f:
    fig = pickle.load(f)

fig.show() # スクリプト1と同じものが表示されるはず

おきたこと

ipythonで順番に打ち込んでいくと出てくるエラーはこちら.まあとにかく表示できない.

In [4]: fig.show()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
C:\Users\hoge\Anaconda3\lib\site-packages\matplotlib\figure.py in show(self, warn)
    380         try:
--> 381             manager = getattr(self.canvas, 'manager')
    382         except AttributeError as err:

AttributeError: 'NoneType' object has no attribute 'manager'

対処

pickle化をfig.show()の前に行うだけ.スクリプト1は以下のようになる.

import matplotlib.pyplot as plt
import pickle

fig = plt.figure()
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)

ax1.plot([1,2,3],[3,2,1])
ax2.plot([1,2,3],[1,2,3]) 

# fig.show()の前に保存する!
# あとで使うために保存
with open("./myfig.pkl", "wb") as f:
    pickle.dump(fig, f)

fig.show()
P.S.

今回の図はこんな感じでした. f:id:nok0714:20170413140253p:plain